TypeScript(タイプスクリプト)は、JavaScriptに静的な型検査を足したMicrosoft製の言語です。書いた型は実行前の検査にだけ使われ、出力されるJavaScriptからは消えます。2026年11月時点のnpmのlatestは7.0.2で、コンパイラはGo製のネイティブ実装に置き換わりました。この記事では、TypeScript 7.0.2で実際に推論させた型を見ながら、型注釈を書く場所と推論に任せる場所の線引き、JavaScriptとの違い、Node.jsで.tsを直接動かすときの制約を説明します。
まとめ:TypeScriptの要点と型注釈の線引き
- TypeScriptはJavaScriptのスーパーセットで、型は実行前に消えます。外から来るデータ(JSONやAPIの応答)が型どおりかは、実行時に自分で確かめる必要があります。
- 型注釈を検討する主な場所は、推論できない関数の引数・公開する関数の戻り値・外部から受け取る値です。公開関数の戻り値への注釈は、意図しない変更を防ぐための設計方針です。初期値のある変数やコールバックの引数は推論に任せたほうが、実装を変えたときに型が追随します。
- TypeScript 6.0から
strictが既定で有効になり、型の書いていない引数は設定ファイルが無くてもエラー(TS7006)になります。5.9までの解説記事とは前提が違います。 - Node.js 22.18以降と23.6以降は、
node app.tsで型を取り除いてそのまま実行します。ただし型検査はしないので、検査にはtsc --noEmitを別に回します。enumのように変換が要る構文は実行時エラーになります。 - 数十行のスクリプトを1本書くだけなら、導入を見送ってかまいません。型が効いてくるのは、他人が書いたコードを変更する機会が増えてからです。
以下、定義と現在の版から順に説明します。
TypeScriptとは:JavaScriptに型検査を足した言語
TypeScriptはMicrosoftが開発し、2012年10月にバージョン0.8として初めて公開されました(Microsoftの公式発表「Announcing TypeScript 1.0」)。JavaScriptの文法はすべてそのまま使え、その上に型の書き方が加わります。拡張子は.ts(JSXを含む場合は.tsx)で、コンパイラtscが型を検査してからJavaScriptを出力します。
利用者は増え続けています。GitHubの年次レポートOctoverse 2025は、2025年8月にTypeScriptが月間コントリビューター数でPythonとJavaScriptを抜き、GitHub上で最も使われている言語になったと報告しています。2024年8月からの1年で、TypeScriptの月間コントリビューターは約105万人(66.63%)増えました。他の言語との比較はプログラミング言語の人気ランキングと推移【2026年10月最新】主要指標で読むトレンドと選び方で扱っています。React・Vue・Angularなどのフロントエンドに加え、Node.jsのサーバー側やCLIツールでも標準的な選択肢です。
型消去:出力されるJavaScriptと実行時検証の限界
TypeScriptの型は、出力されたJavaScriptには残りません。次のコードをtscでコンパイルすると、type Userの宣言も引数の: Userも、as Userも消えます。
type User = { name: string; age: number };
function describe(u: User): string {
return `${u.name} (${u.age})`;
}
const raw = '{"name":"Sato","age":"30"}';
const user = JSON.parse(raw) as User;
console.log(describe(user), typeof user.age);
// tsc 7.0.2 の出力(--module nodenext --target es2022)
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
function describe(u) {
return `${u.name} (${u.age})`;
}
const raw = '{"name":"Sato","age":"30"}';
const user = JSON.parse(raw);
console.log(describe(user), typeof user.age);
実行するとSato (30) stringと表示されます。ageはnumberと宣言したのに、中身は文字列の"30"のままです。as Userは「この値をUserとして扱う」とコンパイラに伝えるだけで、値を検査も変換もしません。型が守ってくれるのは、自分のコードの中で値をやり取りする部分だけです。
2026年のTypeScript:7.0のGo製コンパイラへの移行
TypeScriptは2026年に2回のメジャー更新を挟みました。6.0は既定値を現代向けに切り替える版で、7.0はコンパイラ本体をTypeScriptからGoへ移植した版です。公式ブログのAnnouncing TypeScript 7.0は、7.0を「10倍速いネイティブ移植」と紹介しており、同記事の比較表ではVS Codeのコードベースのビルドが6.0の125.7秒から7.0の10.6秒(11.9倍)に縮んでいます。
| 版 | npm公開日 | 主な変化 |
|---|---|---|
| 5.9.3 | 2025-09-30 | JavaScript実装の最後の5系 |
| 6.0.2 | 2026-03-23 | strict既定true・target es2025 |
| 7.0.2 | 2026-07-08 | Go製ネイティブ実装(現行latest) |
| 7.1.0-beta | 2026-10-20 | 7系の次のマイナー(ベータ) |
公開日はnpm view typescript timeの値です。型の書き方そのものは7.0でも変わっていません。変わったのは既定値と、outFileなどの古いオプションが削除された点です。移行の詳細はTypeScript 7(TS7)とは?Go製tscで約10倍速く|7.0.2への移行とtsgo・7.1 betaの現状とTypeScript 6.0とは|5から6への移行手順とts5to6・7.0との違い【6.0.3対応】で扱っています。
JavaScriptとの違い:型を検査する時期
JavaScriptは動的型付けで、値が型を持ち、変数には異なる型の値を再代入できます。TypeScriptは静的型付けで、コードを動かす前にコンパイラが型の食い違いを報告します。違いは「いつ間違いに気づくか」に集約されます。
| 観点 | JavaScript | TypeScript |
|---|---|---|
| 型付け | 動的(実行時に決まる) | 静的(書いた時点で検査) |
| 型の間違いに気づく時期 | 実行結果や例外の確認時など | エディタ上・tsc実行時 |
| 実行に必要な手順 | そのまま実行 | コンパイルか型除去 |
| 実行時の型保証 | なし | なし(型は消える) |
| 拡張子 | .js / .jsx / .mjs | .ts / .tsx / .mts |
表の「実行時の型保証」はどちらも「なし」です。TypeScriptを入れても実行時の安全性は変わらず、増えるのは書いている最中の安全性です。引数の型を変えたとき、呼び出している全箇所がエディタで赤く表示されるのが、変更の多いコードベースで効く理由です。
型推論に任せる場所:TypeScript 7.0.2が推論した型
TypeScriptは、初期値や戻り値から型を自動で決めます(型推論)。次の表は、各宣言をexport付きで書き、tsc 7.0.2の--declarationで出力した型定義ファイル(.d.ts)の中身です。推論された型がそのまま読めます。
| 書いたコード | 推論された型 |
|---|---|
let a = "hello" |
string |
const b = "hello" |
"hello"(リテラル型) |
const nums = [1, 2, 3] |
number[] |
const mixed = [1, "a"] |
(string | number)[] |
{ kind: "circle" } as const |
{ readonly kind: "circle" } |
nums.map((n) => n * 2) |
number[] |
function greet(name = "guest") { return `hi ${name}`; } |
(name?: string) => string |
export const empty = [] |
never[] |
読み取れることは3つあります。letは後で書き換えられるのでstringに広がり、constは値が固定なので"hello"という1つの値の型になります。mapのコールバックのnは、配列がnumber[]なので注釈なしでnumberと決まります。デフォルト値のある引数も型が決まるので注釈は要りません。
注意が要るのは空配列です。今回の設定でモジュールの最上位にexport const empty = []と書くとnever[]になり、何も追加できません。関数の中で書いた場合はpushした値に応じて型が育ち、push(1)とpush("a")の後に返すと(string | number)[]になりました。最上位で空配列を用意するときはconst ids: number[] = []のように注釈を付けます。
型注釈を書く場所:引数・戻り値・外部データ
型注釈は変数名: 型の形で型を明示する書き方です。推論できる場所に書くと、実装を変えたときに注釈も書き換える手間が増えます。空配列のように意図する型を推論できない変数は前の章のとおり注釈を付け、それ以外では次の3か所を優先して検討します。
関数の引数:推論できない場合の型注釈
関数の引数は、呼び出し側の値から逆算されません。注釈が無いとany(何でも通す型)になり、検査が効かなくなります。TypeScript 6.0でstrictが既定で有効になった(Announcing TypeScript 6.0)ため、設定ファイルが無くても次のコードはエラーになります。
function parse(input) { return input; }
// tsc 7.0.2 infer.ts --noEmit
// error TS7006: Parameter 'input' implicitly has an 'any' type.
同じファイルを5.9.3にオプションなしで渡すと、エラー0件で通ります。古い入門記事のサンプルが7.0.2で動かないときは、まずこの既定値の違いを疑ってください。"strict": falseで黙らせることはできますが、型を書くほうが早く済みます。
公開する関数の戻り値
戻り値は推論されますが、他のファイルから呼ばれる関数には: stringのように明示しておきます。実装を書き換えてreturnの無い経路を作ったとき、: stringがあれば関数の中でTS2366(Function lacks ending return statement)になります。注釈が無いと関数の中ではエラーにならず、戻り値の型がstring | undefinedに変わり、戻り値を文字列として扱っている呼び出し側でエラーになります(noImplicitReturnsを有効にすれば、注釈が無くても関数の中でTS7030として検出できます)。ファイル内でしか使わない小さな関数は推論のままで十分です。
外部データ:unknownによる受け取りと実行時検証
JSON.parseやfetchのresponse.json()はanyを返します。前の章で見たとおり、as Userで型を付けても中身は検査されません。外から来る値はunknownで受け、実行時に形を確かめてから使います。
type User = { name: string; age: number };
function isUser(v: unknown): v is User {
return typeof v === "object" && v !== null &&
typeof (v as Record<string, unknown>).name === "string" &&
typeof (v as Record<string, unknown>).age === "number";
}
const data: unknown = JSON.parse('{"name":"Sato","age":"30"}');
if (isUser(data)) {
console.log(data.age + 1);
} else {
console.log("invalid user");
}
このコードはageが文字列なのでinvalid userを表示します。v is Userは型ガードと呼ばれる書き方で、trueを返した分岐の中ではdataがUserとして扱われます。プロパティが増えると手書きの検査は長くなるので、実務ではZodやArkTypeのような検証ライブラリで型と検査を1か所にまとめます(ArkTypeとは?TypeScript型構文で書く検証ライブラリの使い方とZodとの違い【2.2.9】)。typeof演算子の挙動はtypeofとは?JavaScriptの型判定とTypeScriptのtypeof・keyof、他言語との違い、JSON側の型の対応はJSONの型定義とデータ型一覧|6つの型と変換で消える値、TypeScriptでの書き方にまとめています。
基本の型とユーティリティタイプの早見表
最初に覚える型は多くありません。JavaScriptの値に対応するプリミティブ型と、それを組み合わせる書き方、既存の型から新しい型を作るユーティリティタイプです。
| 分類 | 書き方の例 | 意味 |
|---|---|---|
| プリミティブ | string number boolean |
文字列・数値・真偽値 |
| 配列・タプル | string[] [string, number] |
同じ型の並び・位置ごとの型 |
| ユニオン型 | string | null |
どちらかの型 |
| リテラル型 | "asc" | "desc" |
決まった値だけ許す |
| 型エイリアス | type ID = string |
型に名前を付ける |
| Partial | Partial<User> |
全プロパティを省略可に |
| Pick / Omit | Omit<User, "age"> |
プロパティの抜き出し・除外 |
| Record | Record<string, number> |
キーと値の型を指定した辞書 |
| ReturnType | ReturnType<typeof fn> |
関数の戻り値の型 |
ユーティリティタイプは、元の型を1か所で定義しておき、派生する型をそこから作るために使います。更新用の入力をPartial<User>、一覧表示用をPick<User, "name">と書けば、Userの既存プロパティの型変更が派生側にも反映されます。ただし、新しいプロパティの追加が反映されるのはPartial側で、Pick側は指定したキーだけを保持します。同じ形のオブジェクト型を何度も手書きしているなら、置き換えどきです。文字列の取り違えまで型で防ぎたいときはBranded Types(ブランド型)とは?TypeScriptの書き方とブランドが外れる落とし穴の手法があります。
TypeScriptを動かす:tscとNode.jsの使い分け
TypeScriptのコードを動かす方法は、tscでJavaScriptに変換する方法と、Node.jsに型を取り除かせて直接実行する方法に分かれます。型検査をするのはtscだけです。
tscによる型検査とJavaScript出力
npm install --save-dev typescript @types/node
npx tsc --init
npx tsc --noEmit # 型検査だけ
npx tsc --noEmitOnError # 型エラーがない場合にJavaScriptを出力
7.0.2のtsc --initが生成するtsconfig.jsonは、strict: true・module: "nodenext"・target: "esnext"に加え、"types": []を含みます。このtypesが空のままだと、process.envを書いた行で次のエラーが出ます。
error TS2591: Cannot find name 'process'. Do you need to install type definitions for node?
Try `npm i --save-dev @types/node` and then add 'node' to the types field in your tsconfig.
Node.jsで動かすコードなら、@types/nodeを入れたうえで"types": ["node"]に書き換えます。6.0ではtypesを省略した場合の既定値も[]になりました。ただし、5.9のtsc --initも"types": []を生成するため、その設定では同じ変更が必要です。
Node.jsの型除去による.tsの直接実行
Node.jsは.tsファイルの型の部分を空白に置き換えて、そのまま実行できます。Node.jsのTypeScriptドキュメントによると、この型除去はv23.6.0とv22.18.0で既定で有効になり、v25.2.0とv24.12.0で安定版の扱いになりました。
冒頭の型消去の節にあるTypeScriptコードをhello.tsとして保存し、次のコマンドを実行します。
node hello.ts
手元のNode.js v26.5.0で試すと、ビルドなしで前述のhello.tsが動きました。Node.js以外では、Denoのdeno run main.tsやBunのbun run index.tsも、事前のビルドなしで.tsを実行します。Node.jsの型除去には制約が3つあります。
- 型検査はしません。
const n: number = "abc"; console.log(n);と書いたファイルも、エラーを出さずにabcを表示しました。検査はtsc --noEmitで別に回します。 - JavaScriptへの変換が要る構文は使えません。
enumを書くとERR_UNSUPPORTED_TYPESCRIPT_SYNTAX(TypeScript enum is not supported in strip-only mode)で止まります。名前空間の実行コード・コンストラクタ引数のプロパティ宣言・import aliasも同じです。 .tsxは非対応で、node_modules配下の.tsファイルも実行を拒否します。
変換の要る構文を書いた時点で気づけるよう、tsconfig.jsonに"erasableSyntaxOnly": trueを入れておきます。enumを書くとtscがerror TS1294: This syntax is not allowed when 'erasableSyntaxOnly' is enabled.を出します。enumの代わりには、as constを付けたオブジェクトとリテラル型のユニオンが使えます。
.ts と .tsx の使い分け
.tsxは、ReactなどのJSX(HTMLに似たタグ構文)を含むファイルに使う拡張子です。JSXを書かないファイルは.tsにします。.tsxの中では<User>valueという古い型アサーションの書き方がJSXのタグと区別できないため、value as Userの形しか使えません。上で見たとおりNode.jsの型除去は.tsxを実行しないので、ReactのコードはViteなどのビルドツールで動かします(Vite + Reactの環境構築手順|Viteとは・Vite 8.3の変更点とTypeScript 7対応)。
導入すべき場面と見送ってよい場面
導入すべきなのは、複数人で触るコード・半年以上保守するコード・外部APIの型が頻繁に変わるコードです。関数の引数を1つ変えたときに影響箇所をすべて洗い出せるかどうかが、型の有無で分かれます。
見送ってよいのは、1回限りの集計スクリプトや、数十行で完結するブラウザの小さな処理です。tsconfig.jsonと型定義パッケージの管理が、得られる安全性より重くなります。もう1つ見送る理由になるのは、型の書けない人がチームの大半を占め、全員がanyで逃げる状態になりそうな場合です。anyだらけのTypeScriptは、ビルド手順が増えただけのJavaScriptです。
既存のJavaScriptから移すときは、全ファイルの拡張子を一度に変えなくてかまいません。.jsファイルの先頭に// @ts-checkを書き、JSDocで型を書けば、拡張子はそのままで検査が始まります。
// @ts-check
/** @param {number} a @param {number} b */
function add(a, b) { return a + b; }
add(1, "2");
// tsc 7.0.2 --noEmit --allowJs jsdoc.js
// error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
JSDocを書かずに// @ts-checkだけ付けた場合、7.0.2ではstrictが既定のため、型の無い引数がTS7006で一斉に報告されます。エラーの多いファイルから順に.tsへ移すと、作業量の見通しが立てやすくなります。業務システムの新規開発やJavaScriptからの移行を外部に相談する場合は、業務用・Webアプリ開発の支援内容も参考にしてください。
学習の進め方:最初に読む資料と順番
一次資料は公式のTypeScript Handbookです。ブラウザで試すなら公式のPlaygroundが使え、右側の出力欄で型が消えたJavaScriptと推論された型をその場で確かめられます。日本語で体系的に読みたい場合はサバイバルTypeScriptが実務寄りにまとまっています。
順番は、この記事の流れと同じく「型推論の結果を読む→引数と戻り値に注釈を書く→外部データをunknownで受ける」が効率的です。ジェネリクスや条件型などの型レベルの書き方は、ライブラリの型定義を読む必要が出てからで間に合います。モジュールの分け方はTypeScriptのモジュールとクラスの違い|export/importの書き分けと7.0の変更点、エディタでの静的解析はESLintをVSCodeで使う設定手順|ESLint 10のflat configと保存時の自動修正【10.13対応】が続きの読み物になります。
よくある質問
TypeScriptの読み方は?
「タイプスクリプト」と読みます。略してTSと書かれることも多く、拡張子の.tsもこの略です。
JavaScriptとTypeScriptの違いは何ですか?
型を検査する時期が違います。JavaScript自体には静的な型検査がありませんが、JSDocと型検査ツールを使えば実行前にも検査できます。TypeScriptではコンパイラが型の食い違いを報告します。TypeScriptの型は出力時に消えるので、実行時の動作はJavaScriptと同じです。
TypeScriptの型チェックはいつ実行されますか?
エディタで編集している最中と、tscを実行したときです。Node.jsで.tsを直接実行する場合やViteなどのビルドツールで変換する場合は型を取り除くだけで検査しないため、CIなどでtsc --noEmitを別に回します。
TypeScriptの欠点は何ですか?
型定義とtsconfig.jsonの管理が増えることと、実行時の値は保証されないことです。外部データはunknownで受けて検査しないと、型と中身が食い違ったまま動きます。また7.0では古いオプションが削除されたため、古い設定ファイルや入門記事のサンプルがそのままでは通らない場合があります。
PythonとTypeScriptの違いは何ですか?
どちらも型の情報を書けますが、Pythonの型ヒントはPEP 484のとおり実行時には検査されず、mypyなどの別ツールで検査します。TypeScriptは型検査がコンパイラに組み込まれている点と、実行環境がJavaScript(ブラウザやNode.js)である点が違います。