TypeScript基本型一覧|主要なデータ型と使い方をわかりやすく解説
TypeScriptは、JavaScriptに型システムを追加したプログラミング言語です。JavaScriptは柔軟にコードを書ける一方で、変数にどのような値が入るのか、関数がどのような値を返すのかが分かりにくくなることがあります。小規模なコードであれば問題になりにくい場合もありますが、アプリケーションが大きくなるほど、型の曖昧さはバグや保守性低下の原因になります。
TypeScriptでは、変数、関数の引数、戻り値、オブジェクト、配列などに型を指定できます。型を明確にすることで、コードを書く段階で誤りに気づきやすくなり、エディタの補完も効きやすくなります。また、チーム開発では「この関数には何を渡せばよいのか」「この値はどの形式で返ってくるのか」をコード上で共有できるため、仕様理解もしやすくなります。
TypeScriptを学習する際は、まず基本型を理解することが重要です。文字列、数値、真偽値、配列、オブジェクト、タプル、列挙型、任意型、不明型、戻り値なし型、到達不能型などを理解しておくと、実務で型定義を読む力と書く力が身につきます。本記事では、TypeScriptの主要な基本型を一覧で整理し、それぞれの特徴と使い方をコード例付きで解説します。
1. TypeScript基本型とは?
TypeScript基本型とは、変数や関数、データ構造に対して指定できる代表的な型のことです。JavaScriptで扱う値には、文字列、数値、真偽値、配列、オブジェクトなどがありますが、TypeScriptではそれらに明示的な型を付けることで、コードの意味をより明確にできます。たとえば、ユーザー名には文字列型、年齢には数値型、ログイン状態には真偽値型を指定することで、意図しない値が入ることを防ぎやすくなります。
TypeScriptの基本型は、単に文法として覚えるだけではなく、「どのような場面で使うか」を理解することが大切です。たとえば、外部APIから取得した値には不明型を使い、検証後に具体的な型として扱う方が安全です。関数が値を返さない場合は戻り値なし型を使い、例外を投げる関数や無限ループする関数には到達不能型が関係します。このように、型は値の種類だけでなく、プログラムの意図や制約を表す役割も持っています。
TypeScript基本型の主な特徴
| 型 | 用途 |
|---|---|
string | 文字列を扱う |
number | 数値を扱う |
boolean | 真偽値を扱う |
array | 同じ型の値を複数扱う |
tuple | 要素数と各要素の型が決まった配列を扱う |
enum | 名前付きの定数グループを扱う |
any | 型チェックを無効に近い状態で扱う |
unknown | 型が不明な値を安全に扱う |
void | 値を返さない関数を表す |
never | 到達しない処理や戻らない関数を表す |
object | オブジェクト型の値を扱う |
null / undefined | 値が存在しない状態を扱う |
1.1 TypeScript基本型の概要
TypeScriptでは、変数に型を付けることで、その変数に入れられる値の種類を制限できます。たとえば、stringと指定した変数には文字列を入れることができ、数値を代入しようとするとコンパイル時にエラーとして検出されます。JavaScriptでは実行して初めて気づくようなミスも、TypeScriptでは開発中に発見しやすくなります。
また、TypeScriptは型推論にも対応しています。つまり、すべての変数に明示的な型を書かなくても、代入された値からTypeScriptが型を推測してくれます。ただし、学習段階では基本型を理解するために、明示的に型を書く練習をしておくとよいでしょう。型推論に頼る場面と、明示的に型を書く場面を使い分けられるようになると、より読みやすく安全なコードを書けるようになります。
TypeScript
index.ts
const userName: string = "Taro";const age: number = 25;const isActive: boolean = true;
1.2 TypeScript基本型を利用するメリット
TypeScript基本型を利用する最大のメリットは、コードの安全性が高まることです。たとえば、本来は数値であるべき値に文字列が入ってしまうと、計算処理で予期しない結果になることがあります。TypeScriptで型を指定しておけば、そのようなミスを開発段階で検出しやすくなります。特に、フォーム入力、APIレスポンス、データベースから取得した値など、値の形式が重要になる場面では型の効果が大きくなります。
さらに、型はコードのドキュメントとしても機能します。関数の引数や戻り値に型が書かれていれば、その関数が何を受け取り、何を返すのかが一目で分かります。チーム開発では、他の人が書いたコードを読む機会が多いため、型によって意図が明確になることは大きなメリットです。型安全性の向上、コード補完の強化、バグ削減、保守性向上は、TypeScriptを導入する代表的な理由といえます。
2. 文字列型
文字列型は、名前、メールアドレス、住所、メッセージ、タイトル、説明文など、テキストデータを扱うための型です。TypeScriptではstringを使って文字列型を指定します。JavaScriptと同じく、シングルクォート、ダブルクォート、バッククォートを使って文字列を表現できます。バッククォートを使えば、変数を埋め込むテンプレート文字列も利用できます。
文字列型は最もよく使う基本型の一つです。Webアプリでは、ユーザー名、検索キーワード、フォーム入力値、APIから返るラベル名など、多くのデータが文字列として扱われます。文字列型を正しく指定しておくことで、数値や真偽値を誤って代入するミスを防ぎやすくなります。
2.1 文字列型とは?
文字列型は、テキストを表す値に使います。変数にstringを指定すると、その変数には文字列だけを代入できるようになります。たとえば、ユーザー名を表す変数に数値を入れようとすると、TypeScriptが型エラーとして検出します。これにより、値の意味と使い方が明確になります。
文字列型は、画面表示や入力値の管理だけでなく、条件分岐やデータ整形にもよく使われます。たとえば、ユーザーのステータス、カテゴリ名、メッセージ種別などを文字列で管理する場合があります。ただし、決まった文字列だけを許可したい場合は、単なるstringではなく、後述するリテラル型や共用体型を使うとより安全です。
TypeScript
index.ts
const name: string = "Taro";const message: string = "Hello TypeScript";const email: string = "[email protected]";
2.2 テンプレート文字列で使う
文字列型では、バッククォートを使ったテンプレート文字列もよく使われます。テンプレート文字列を使うと、変数や式を文字列の中に埋め込むことができます。ユーザー名を含むメッセージや、数値を含む説明文を作る場合に便利です。
テンプレート文字列は、文字列連結よりも読みやすくなりやすい点がメリットです。特に、複数の値を組み合わせて文章を作る場合、+で連結するよりも構造が分かりやすくなります。TypeScriptでは、埋め込む値の型も確認されるため、意図しない値を扱っていないか確認しやすくなります。
TypeScript
index.ts
const userName: string = "Hanako";const age: number = 28;const profile: string = `${userName}さんは${age}歳です。`;
2.3 文字列型を使う場面
文字列型は、ユーザー入力、APIレスポンス、画面表示、ログ出力、検索条件など、幅広い場面で利用されます。たとえば、フォームで入力された氏名やメールアドレスは文字列として扱われます。また、記事タイトル、商品名、カテゴリ名、通知メッセージなども文字列型で定義されることが多いです。
ただし、すべてをstringにすればよいわけではありません。たとえば、ステータスが「下書き」「公開」「非公開」の3種類だけである場合、単なるstringではどんな文字列でも入ってしまいます。このような場合は、文字列リテラル型を使って許可する値を限定すると、より安全なコードになります。
3. 数値型
数値型は、価格、年齢、数量、スコア、座標、割合、IDの一部など、数値を扱うための型です。TypeScriptではnumberを使って数値型を指定します。JavaScriptと同じく、整数と小数を区別せず、どちらもnumberとして扱います。TypeScript公式ドキュメントでも、JavaScriptの主要なプリミティブ値としてstring、number、booleanが説明されています。
数値型は計算処理に使われるため、誤った型が入るとバグにつながりやすい領域です。たとえば、価格計算で文字列が混ざると、足し算ではなく文字列結合になってしまう可能性があります。TypeScriptで数値型を指定しておくことで、このようなミスを防ぎやすくなります。
3.1 数値型とは?
数値型は、数値を表す値に使います。整数、小数、負の数などを扱うことができ、計算処理や比較処理でよく利用されます。たとえば、商品の価格、在庫数、ユーザーの年齢、ページ番号、評価スコアなどは数値型として定義できます。
TypeScriptでは、数値型を指定しておくことで、数値以外の値を誤って代入することを防げます。特に、APIやフォームから受け取る値は文字列になっている場合も多いため、数値として扱う前に変換や検証を行うことが重要です。
TypeScript
index.ts
const price: number = 1200;const taxRate: number = 0.1;const total: number = price + price * taxRate;
3.2 整数と小数の扱い
TypeScriptのnumber型は、整数と小数を同じ型として扱います。たとえば、10も10.5も同じnumber型です。そのため、「整数だけを許可したい」「0以上の数値だけを許可したい」といった制約は、型だけではなくロジックやバリデーションで補う必要があります。
実務では、数値型に加えて入力チェックを行うことが重要です。たとえば、年齢であれば0未満にならないようにする、数量であれば整数だけを許可する、割合であれば0から100の範囲に収める、といった制約が必要です。TypeScriptの型は値の種類を管理できますが、業務ルールまですべて自動で保証するわけではありません。
TypeScript
index.ts
const count: number = 10;const average: number = 87.5;const temperature: number = -3.2;
3.3 数値型を使う場面
数値型は、計算が必要なあらゆる場面で使います。ECサイトであれば価格、送料、割引率、注文数量などが数値型になります。ダッシュボードであれば売上、アクセス数、コンバージョン率、平均滞在時間などが数値型になります。ゲーム開発であればHP、攻撃力、速度、座標、スコアなども数値型として扱います。
ただし、電話番号や郵便番号のように数字だけで構成されていても、計算しない値は文字列型にする方が適切です。電話番号を数値型にすると先頭の0が消えたり、桁数の扱いが難しくなったりします。数値型は「計算対象かどうか」を基準に使うと判断しやすくなります。
4. 真偽値型
真偽値型は、trueまたはfalseのどちらかを扱うための型です。TypeScriptではbooleanを使って指定します。ログインしているか、表示するか、完了しているか、有効か無効か、権限があるかなど、状態を表す場面でよく利用されます。
真偽値型は、条件分岐と相性が良い型です。たとえば、isLoggedInがtrueならマイページを表示し、falseならログイン画面を表示する、といった処理を分かりやすく書けます。変数名には、is、has、canなどを付けると、真偽値であることが読み取りやすくなります。
4.1 真偽値型とは?
真偽値型は、二択の状態を表すために使います。たとえば、ユーザーがアクティブかどうか、タスクが完了しているかどうか、ボタンを無効化するかどうかなどを表現できます。boolean型を指定することで、文字列や数値を誤って代入することを防げます。
真偽値型はシンプルですが、使い方を誤るとコードが読みにくくなることもあります。たとえば、flagのような曖昧な名前では、何を意味する真偽値なのか分かりません。isActive、hasPermission、canEditのように、状態や権限が明確に分かる名前を付けることが重要です。
TypeScript
index.ts
const isLoggedIn: boolean = true;const isAdmin: boolean = false;const hasPermission: boolean = true;
4.2 条件分岐で使う
真偽値型は、if文や三項演算子などの条件分岐でよく使われます。状態に応じて表示内容や処理を切り替える場合、真偽値型を使うことでコードの意図が明確になります。たとえば、ログイン済みであればユーザー名を表示し、未ログインであればログインボタンを表示する、といった処理です。
TypeScriptでは、真偽値型の変数に誤って文字列や数値を代入するとエラーになります。これにより、条件分岐で意図しない値が使われるリスクを減らせます。JavaScriptでは0や空文字列なども条件式で真偽値のように扱われますが、TypeScriptでは明示的にbooleanを使うことで意味をはっきりさせやすくなります。
TypeScript
index.ts
const isMember: boolean = true;if (isMember) { console.log("会員ページを表示します。");} else { console.log("ログインページを表示します。");}
4.3 真偽値型を使う場面
真偽値型は、状態管理、権限管理、表示制御、入力チェック、処理結果の判定などでよく使われます。ReactなどのUI開発では、モーダルを開いているか、ローディング中か、エラーがあるか、チェックボックスが選択されているかなどをbooleanで管理することが多いです。
ただし、状態が3種類以上ある場合は、真偽値型だけでは表現しにくくなります。たとえば、通信状態が「未開始」「読み込み中」「成功」「失敗」の4種類ある場合、booleanを複数使うよりも、文字列リテラル型や列挙型で状態を表す方が分かりやすくなります。
5. 配列型
配列型は、同じ種類の値を複数まとめて扱うための型です。TypeScriptでは、string[]やnumber[]のように書く方法と、Array<string>やArray<number>のように書く方法があります。公式ドキュメントでも、number[]とArray<number>は同じ意味を表す書き方として説明されています。
配列型は、一覧データを扱う場面で非常によく使います。ユーザー一覧、商品一覧、記事一覧、タグ一覧、スコア一覧など、複数のデータをまとめて処理する場合に利用します。配列の中に入る値の型を指定しておくことで、誤った値が混ざることを防ぎやすくなります。
5.1 配列型とは?
配列型は、同じ型の値を複数格納するための型です。たとえば、文字列の一覧であればstring[]、数値の一覧であればnumber[]と指定します。これにより、文字列配列に数値を追加しようとした場合などに、TypeScriptがエラーを出してくれます。
配列型は、データを一覧表示したり、繰り返し処理したりする場面で欠かせません。map、filter、reduceなどの配列メソッドを使う際にも、配列の要素型が明確であれば、エディタ補完や型チェックが効きやすくなります。
TypeScript
index.ts
const names: string[] = ["Taro", "Hanako", "Jiro"];const scores: number[] = [80, 95, 72];const tags: Array<string> = ["TypeScript", "React", "Frontend"];
5.2 オブジェクト配列
実務では、単純な文字列配列や数値配列だけでなく、オブジェクトの配列を扱うことが多くあります。たとえば、ユーザー一覧や商品一覧は、各要素が複数のプロパティを持つオブジェクトになります。この場合は、オブジェクトの型を定義し、その配列として扱うと分かりやすくなります。
オブジェクト配列では、各要素の構造を明確にすることが重要です。名前、年齢、メールアドレス、ステータスなど、どのプロパティを持つのかを型として定義しておけば、一覧処理や画面表示でミスを減らせます。プロパティ名のタイプミスも検出しやすくなるため、保守性が高まります。
TypeScript
index.ts
type User = { id: number; name: string; email: string;};const users: User[] = [ { id: 1, name: "Taro", email: "[email protected]" }, { id: 2, name: "Hanako", email: "[email protected]" },];
5.3 配列型を使う場面
配列型は、APIから取得した一覧データ、画面に表示するリスト、検索結果、選択肢、ログ、タグ、カテゴリなどに使われます。Webアプリでは、ほとんどの一覧表示が配列型と関係します。配列の要素型を明確にしておくことで、データを取り出したときにどのプロパティやメソッドが使えるか分かりやすくなります。
配列型を扱う際は、空配列の型推論にも注意が必要です。空配列だけを書くと、文脈によっては意図しない型に推論されることがあります。実務では、空配列で初期化する場合でも、const items: Item[] = []のように型を明示しておくと安全です。
6. タプル型
タプル型は、要素数と各要素の型が決まっている配列を表す型です。通常の配列は同じ型の値を複数扱うことが多いですが、タプルでは「1番目は文字列、2番目は数値」のように、位置ごとに異なる型を指定できます。TypeScriptでは、[string, number]のように書きます。
タプル型は、複数の値を決まった順番で返したい場合や、座標のように意味のある固定長データを扱う場合に便利です。ただし、位置で意味が決まるため、要素が増えすぎると読みづらくなることがあります。データの意味を明確にしたい場合は、オブジェクト型を使う方が分かりやすいこともあります。
6.1 タプル型とは?
タプル型は、配列のように見えますが、通常の配列よりも構造が厳密です。たとえば、[string, number]という型は、1番目に文字列、2番目に数値を持つ配列を表します。順番や型が違う値を代入しようとすると、TypeScriptがエラーとして検出します。
この性質により、タプル型は固定された形式のデータを扱う場合に役立ちます。たとえば、座標を[number, number]で表したり、APIの簡易的な戻り値を[boolean, string]で表したりできます。ただし、意味が分かりにくくなる場合は、名前付きプロパティを持つオブジェクトにした方が読みやすくなります。
TypeScript
index.ts
const user: [string, number] = ["Taro", 25];const point: [number, number] = [120, 80];
6.2 タプル型の注意点
タプル型は便利ですが、使いすぎるとコードの意味が分かりにくくなることがあります。たとえば、[string, number, boolean]という型だけを見ても、それぞれが何を意味しているのか分かりにくい場合があります。要素数が多い場合や、各値の意味が重要な場合は、オブジェクト型で名前を付ける方が適切です。
また、タプル型は順番が重要です。1番目と2番目の値を入れ替えると意味が変わってしまいます。座標や簡単な戻り値のように、順番で意味を理解しやすい場面では有効ですが、業務データのように意味が多い情報には慎重に使いましょう。
TypeScript
index.ts
const result: [boolean, string] = [true, "保存に成功しました。"];const isSuccess: boolean = result[0];const message: string = result[1];
6.3 タプル型を使う場面
タプル型は、座標、範囲、ペアデータ、簡易的な戻り値などに使われます。たとえば、[開始日, 終了日]、[x座標, y座標]、[成功可否, メッセージ]のような固定された組み合わせに向いています。要素数が少なく、順番の意味が明確な場合は、タプル型を使うと簡潔に表現できます。
一方で、タプル型を使うかオブジェクト型を使うかは、読みやすさで判断することが重要です。チーム開発では、後から読む人が意味を理解しやすいことが大切です。タプル型が分かりにくいと感じる場合は、{ isSuccess: boolean; message: string }のようなオブジェクト型にした方がよいでしょう。
7. 列挙型
列挙型は、関連する定数を名前付きでまとめるための型です。TypeScriptではenumを使って定義できます。たとえば、ユーザーの権限、注文ステータス、画面モード、曜日、方向など、決まった候補の中から値を選ぶ場面で利用されます。
ただし、近年のTypeScript開発では、enumの代わりに文字列リテラル型やas constを使うケースも増えています。enumは便利ですが、生成されるJavaScriptコードや扱いに注意が必要な場面もあります。そのため、基本として理解しつつ、実務ではプロジェクトの方針に合わせて使うことが大切です。
7.1 列挙型とは?
列挙型は、複数の定数を一つのまとまりとして扱うための仕組みです。たとえば、ユーザー権限としてAdmin、Editor、Viewerを定義しておけば、権限の値を安全に扱いやすくなります。文字列を直接書くよりも、定義された候補から選ぶ形になるため、タイプミスを減らせます。
列挙型は、コード上で意味のある名前を付けたい場合に便利です。数値や文字列をそのまま使うと意味が分かりにくい場合でも、列挙型にすることで値の役割が明確になります。ただし、単純な文字列の候補を表すだけなら、文字列リテラル型の方が軽量で扱いやすい場合もあります。
TypeScript
index.ts
enum UserRole { Admin = "ADMIN", Editor = "EDITOR", Viewer = "VIEWER",}const role: UserRole = UserRole.Admin;
7.2 数値列挙型と文字列列挙型
TypeScriptの列挙型には、数値列挙型と文字列列挙型があります。数値列挙型では、値を指定しない場合に0から順番に数値が割り当てられます。一方、文字列列挙型では、それぞれの値に文字列を明示します。実務では、ログやAPI通信で意味が分かりやすい文字列列挙型が使われることも多いです。
文字列列挙型のメリットは、実際の値を見たときに意味を理解しやすいことです。たとえば、"PENDING"や"COMPLETED"のような値は、数値の0や1よりも状態を判断しやすくなります。APIやデータベースと連携する場合にも、文字列の方が扱いやすいことがあります。
TypeScript
index.ts
enum OrderStatus { Pending = "PENDING", Paid = "PAID", Shipped = "SHIPPED", Canceled = "CANCELED",}const status: OrderStatus = OrderStatus.Paid;
7.3 列挙型を使う場面
列挙型は、決まった候補の中から値を選ぶ場面で使います。注文ステータス、ユーザー権限、通知種別、画面モード、エラー種別などが代表例です。値の種類が限定されている場合、列挙型を使うことでコードの意図を明確にできます。
ただし、列挙型を使うか、文字列リテラル型を使うかは検討が必要です。小規模な型定義やReactの状態管理では、type Status = "pending" | "paid" | "shipped"のような書き方の方がシンプルな場合があります。列挙型は、定数として再利用したい場合や、チームで明確な定義を共有したい場合に有効です。
8. 任意型
任意型は、どのような型の値でも受け入れる型です。TypeScriptではanyを使って指定します。anyを使うと、TypeScriptの型チェックが大きく緩くなり、文字列、数値、真偽値、配列、オブジェクトなど、どのような値でも代入できます。そのため、JavaScriptからTypeScriptへ移行する段階や、型が不明な外部ライブラリを扱う場面で使われることがあります。
しかし、anyを多用するとTypeScriptのメリットが失われます。型安全性が低下し、存在しないプロパティにアクセスしてもエラーにならない場合があります。結果として、JavaScriptと同じように実行時エラーが起こりやすくなります。任意型は便利な逃げ道ですが、最終手段として慎重に使うべき型です。
8.1 任意型とは?
任意型は、値の型を問わずに扱える型です。anyを指定した変数には、文字列を入れた後に数値を入れることもできます。また、存在しないメソッドを呼び出しても、TypeScriptが厳密にチェックできない場合があります。これは一見便利ですが、型による安全性が失われることを意味します。
任意型は、TypeScriptの導入初期や、型定義が存在しない古いライブラリを扱う場合に一時的に使われることがあります。ただし、長期的にはanyを減らし、具体的な型や不明型に置き換えることが望ましいです。安全なTypeScriptコードを書くには、anyを使う理由を明確にする必要があります。
TypeScript
index.ts
let value: any = "Hello";value = 123;value = true;
8.2 任意型の危険性
任意型の危険性は、型チェックが弱くなることです。たとえば、any型の値に対して存在しないプロパティやメソッドを呼び出しても、コンパイル時に検出できない場合があります。その結果、実行時にエラーが発生する可能性があります。TypeScriptを使っているにもかかわらず、型安全性の恩恵を受けにくくなります。
特に、プロジェクト全体でanyが増えると、どこでどのような値が使われているのか分かりにくくなります。チーム開発では、anyの多用が保守性を下げる原因になります。どうしても使う場合は、一時的な利用にとどめ、あとで具体的な型に置き換える方針を持つことが重要です。
TypeScript
index.ts
let user: any = { name: "Taro" };// 実行時に問題になる可能性があるconsole.log(user.age.toUpperCase());
8.3 任意型を使う場面
任意型は、型がどうしても分からないデータを一時的に扱う場合に使えます。たとえば、JavaScriptからTypeScriptへ移行する途中、外部ライブラリの型定義がない場合、古いコードを段階的に型付けする場合などです。ただし、新しく書くコードでは、できるだけanyを避ける方が安全です。
型が不明な値を扱う場合は、anyではなくunknownを使う方が推奨されることが多いです。不明型は、型チェックを行うまで値を自由に使えないため、より安全に扱えます。任意型は便利ですが、TypeScriptの型安全性を無効化する強い型であることを理解して使いましょう。
9. 不明型
不明型は、型がまだ分からない値を安全に扱うための型です。TypeScriptではunknownを使って指定します。unknownはanyと似ていますが、値をそのまま自由に操作できない点が大きく異なります。値を使う前に、typeofや条件分岐などで型を確認する必要があります。
不明型は、外部から入ってくるデータを扱う場合に有効です。たとえば、APIレスポンス、ユーザー入力、JSON解析結果、外部ライブラリから返る値などは、実際にどのような型か分からない場合があります。そのような値をunknownとして受け取り、検証してから具体的な型として扱うことで、安全性を高められます。
9.1 不明型とは?
不明型は、「どの型か分からない値」を表します。unknown型の変数には、文字列、数値、真偽値、オブジェクトなど何でも代入できます。しかし、その値を文字列として扱ったり、数値として計算したりするには、事前に型を確認する必要があります。
この制約により、unknownはanyより安全です。anyでは誤った操作をしてもコンパイル時に検出できない場合がありますが、unknownでは型確認なしに操作しようとするとエラーになります。つまり、unknownは「何でも入るが、確認しないと使えない型」と考えると分かりやすいです。
TypeScript
index.ts
let value: unknown = "Hello TypeScript";if (typeof value === "string") { console.log(value.toUpperCase());}
9.2 不明型と任意型の違い
不明型と任意型の違いは、安全性にあります。anyは型チェックを大きく回避できるため、自由に操作できます。一方、unknownは型が分からない値として扱われるため、型を確認しない限り具体的な操作ができません。この違いにより、unknownは安全なコードを書きやすくなります。
外部データを扱う場合は、まずunknownとして受け取り、必要な検証を行ってから使うのが安全です。たとえば、APIから返る値が本当に文字列なのか、オブジェクトなのか、配列なのかを確認してから処理することで、実行時エラーを減らせます。
TypeScript
index.ts
let data: unknown = 100;// 型確認を行うif (typeof data === "number") { console.log(data + 50);}
9.3 不明型を使う場面
不明型は、外部から入ってくる信頼できない値を扱う場面で使います。APIレスポンス、フォーム入力、JSONファイル、外部ライブラリ、エラーオブジェクトなどは、想定と異なる形式になる可能性があります。そのような値をいきなり具体的な型として扱うのではなく、unknownで受け取り、型ガードで確認することで安全になります。
実務では、unknownと型ガードを組み合わせることが重要です。たとえば、値が文字列か確認する関数、オブジェクトが特定のプロパティを持つか確認する関数を作ることで、外部データを安全に扱えます。unknownは少し手間が増えますが、その分安全性を高められる型です。
10. 戻り値なし型
戻り値なし型は、関数が値を返さないことを表す型です。TypeScriptではvoidを使います。たとえば、コンソールにログを出す関数、画面表示を更新する関数、イベントを処理する関数など、戻り値を使わない関数に指定します。
voidは、関数の目的を明確にするために役立ちます。戻り値がないことを型として示すことで、その関数が値を返すためのものではなく、何らかの処理を実行するためのものだと分かります。特に、イベントハンドラーや副作用を持つ処理ではよく使われます。
10.1 戻り値なし型とは?
戻り値なし型は、関数が明示的な値を返さないことを表します。return文を書かない関数や、return;だけで終了する関数は、戻り値として利用できる値を返しません。このような関数にvoidを指定します。
voidを指定することで、関数の利用者に「この関数の戻り値を使うべきではない」と伝えられます。たとえば、ログ出力や通知表示のような処理は、戻り値よりも処理そのものが目的です。こうした関数ではvoidを使うと意図が明確になります。
TypeScript
index.ts
function logMessage(message: string): void { console.log(message);}
10.2 イベント処理で使う
戻り値なし型は、イベント処理でよく使われます。ボタンをクリックしたとき、フォームを送信したとき、入力値が変わったときなど、何かの操作に応じて処理を実行する関数は、戻り値を使わないことが多いです。このような関数にvoidを指定すると、処理の目的が分かりやすくなります。
Reactなどのフロントエンド開発でも、イベントハンドラーはvoidを返すことが多くあります。たとえば、クリック時に状態を更新する関数は、値を返す必要がありません。戻り値なし型を理解しておくと、UIイベント処理の型定義も読みやすくなります。
TypeScript
index.ts
function handleClick(): void { console.log("ボタンがクリックされました。");}
10.3 戻り値なし型を使う場面
戻り値なし型は、ログ出力、通知表示、状態更新、イベント処理、保存処理の呼び出しなど、結果の値を返さない関数で使います。関数が何らかの副作用を起こすことが目的である場合、voidを指定すると意図が明確になります。
ただし、関数が値を返すべきかどうかは設計上重要です。処理の結果を呼び出し元で使う必要がある場合は、voidではなく適切な戻り値の型を指定すべきです。たとえば、保存に成功したかどうかを呼び出し元で判断したいなら、booleanや結果オブジェクトを返す設計にする方が適切です。
11. 到達不能型
到達不能型は、関数が正常に値を返すことがない場合や、到達しないコードを表す型です。TypeScriptではneverを使います。たとえば、必ず例外を投げる関数、無限ループする関数、すべての分岐を処理し尽くした後の到達不能な場所などに関係します。
neverは初心者には少し分かりにくい型ですが、型安全な設計では重要です。特に、状態や種類を表す共用体型と組み合わせると、処理漏れを検出するために使えます。たとえば、注文ステータスが増えたのに分岐処理を更新していない場合、neverを使うことで気づきやすくなります。
11.1 到達不能型とは?
到達不能型は、「この値は発生しない」「この関数は戻らない」という意味を持つ型です。たとえば、関数内で必ず例外を投げる場合、その関数は通常の戻り値を返しません。このような関数の戻り値型はneverになります。
voidとneverは似て見えるかもしれませんが、意味は異なります。voidは「値を返さないが、関数は終了する」ことを表します。一方、neverは「正常に終了しない」または「到達しない」ことを表します。この違いを理解すると、エラー処理や網羅性チェックで役立ちます。
TypeScript
index.ts
function throwError(message: string): never { throw new Error(message);}
11.2 網羅性チェックで使う
到達不能型は、共用体型の網羅性チェックでよく使われます。たとえば、ステータスが"success"、"error"、"loading"の3種類ある場合、すべてのケースを処理しているか確認できます。もし新しいステータスが追加されたのに処理が漏れていると、neverを使ったチェックで気づきやすくなります。
網羅性チェックは、実務で非常に有効です。状態の種類が増えたとき、すべての分岐を手動で確認するのは大変です。TypeScriptの型システムを使って処理漏れを検出できれば、変更に強いコードになります。
TypeScript
index.ts
type Status = "success" | "error" | "loading";function handleStatus(status: Status): string { switch (status) { case "success": return "成功しました。"; case "error": return "エラーが発生しました。"; case "loading": return "読み込み中です。"; default: const neverValue: never = status; return neverValue; }}
11.3 到達不能型を使う場面
到達不能型は、例外を投げる関数、無限ループする関数、到達不能な分岐、網羅性チェックなどで使います。普段の変数定義で頻繁に使う型ではありませんが、型安全な設計を行ううえで重要な役割を持っています。
特に、状態管理やドメインロジックを厳密に扱う場合、neverを使った網羅性チェックは有効です。ステータスや種別が増えたときに、未対応の処理をコンパイル時に検出しやすくなるため、保守性の高いコードにつながります。
12. オブジェクト型
オブジェクト型は、複数のプロパティを持つデータ構造を表すための型です。TypeScriptでは、{ name: string; age: number }のようにプロパティ名と型を指定します。公式ドキュメントでも、JavaScriptではデータをまとめて渡す基本的な方法としてオブジェクトが使われ、TypeScriptではそれをオブジェクト型で表現すると説明されています。
実務のTypeScript開発では、オブジェクト型が非常に重要です。ユーザー、商品、記事、注文、設定、APIレスポンスなど、多くのデータはオブジェクトとして扱われます。オブジェクト型を正しく定義することで、データ構造を明確にし、プロパティのタイプミスや不足を防ぎやすくなります。
12.1 オブジェクト型とは?
オブジェクト型は、プロパティの名前と型をまとめて定義します。たとえば、ユーザー情報であれば、idは数値、nameは文字列、isActiveは真偽値のように指定できます。これにより、ユーザーオブジェクトがどのような形を持つべきかを明確にできます。
オブジェクト型は、関数の引数やAPIレスポンスの型定義でよく使われます。関数が受け取るオブジェクトの構造を型として定義しておけば、必要なプロパティが不足している場合や、型が違う場合にエラーとして検出できます。
TypeScript
index.ts
const user: { id: number; name: string; isActive: boolean } = { id: 1, name: "Taro", isActive: true,};
12.2 型別名で定義する
オブジェクト型は、そのまま書くこともできますが、再利用する場合は型別名を使うと便利です。type User = { ... }のように定義しておけば、変数、関数の引数、戻り値などで同じ型を使い回せます。これにより、コードの重複を減らし、データ構造の変更にも対応しやすくなります。
型別名を使うと、コードの意味も分かりやすくなります。単に{ id: number; name: string }と書くよりも、Userという名前が付いている方が、そのデータが何を表すのか理解しやすくなります。実務では、オブジェクト型を型別名やインターフェースとして定義することが多いです。
TypeScript
index.ts
type User = { id: number; name: string; email: string; isActive: boolean;};const user: User = { id: 1, name: "Taro", email: "[email protected]", isActive: true,};
12.3 オブジェクト型を使う場面
オブジェクト型は、アプリケーションで扱うほとんどの業務データに使われます。ユーザー情報、商品情報、注文情報、記事情報、設定情報、フォーム入力値、APIレスポンスなどが代表例です。データの構造を型として定義することで、コード全体で一貫した扱いができるようになります。
オブジェクト型では、任意プロパティや読み取り専用プロパティも定義できます。たとえば、description?: stringのように書けば、説明文があってもなくてもよいことを表せます。readonly id: numberのように書けば、IDを後から変更しない設計にできます。基本型を理解した後は、こうしたオブジェクト型の発展的な使い方も学ぶとよいでしょう。
13. null型とundefined型
nullとundefinedは、値が存在しない状態を表すために使われます。undefinedは値がまだ代入されていない状態を表すことが多く、nullは意図的に値がないことを示すために使われることがあります。TypeScriptでは、設定によってnullやundefinedの扱いが厳密になります。
実務では、値が存在しない可能性を型で表すことが重要です。たとえば、ユーザーのプロフィール画像が未設定の場合、画像URLはstringではなくstring | nullのように定義する方が現実的です。これにより、値がない場合の処理を忘れにくくなります。
13.1 null型とは?
nullは、値が意図的に存在しないことを表す値です。たとえば、ユーザーがプロフィール画像を設定していない場合や、検索結果が存在しない場合にnullを使うことがあります。nullを型に含めることで、値が存在しない可能性を明確にできます。
nullを扱う場合は、利用前にチェックすることが重要です。nullの可能性がある値に対して、そのまま文字列メソッドやプロパティアクセスを行うとエラーになります。TypeScriptでは、if文などでnullチェックを行うことで、安全に値を扱えます。
TypeScript
index.ts
let profileImageUrl: string | null = null;if (profileImageUrl !== null) { console.log(profileImageUrl);}
13.2 undefined型とは?
undefinedは、値がまだ定義されていない状態を表します。オブジェクトの任意プロパティや、値が返らない場合などで登場します。たとえば、オブジェクトに存在しないプロパティへアクセスするとundefinedになることがあります。
TypeScriptでは、任意プロパティを?で表現できます。たとえば、description?: stringと書くと、descriptionは存在してもよいし、存在しなくてもよいプロパティになります。この場合、値を使う前にundefinedの可能性を考慮する必要があります。
TypeScript
index.ts
type Product = { id: number; name: string; description?: string;};const product: Product = { id: 1, name: "Keyboard",};console.log(product.description);
13.3 nullとundefinedを使う場面
nullとundefinedは、値がない状態を表すために使いますが、プロジェクト内で使い分けの方針を決めておくことが重要です。APIやデータベースではnullが返ることが多く、JavaScriptのオブジェクトや任意プロパティではundefinedが出やすい傾向があります。どちらも無秩序に使うと、値の存在チェックが複雑になります。
実務では、strictNullChecksを有効にして、nullやundefinedの可能性を型で明確にすることが推奨されます。値が存在しない可能性を型に含めておけば、処理前にチェックする習慣がつき、実行時エラーを減らしやすくなります。
14. 共用体型
共用体型は、複数の型のうちいずれかを許可する型です。TypeScriptでは|を使って表現します。たとえば、string | numberと書くと、文字列または数値を受け入れる型になります。共用体型は、柔軟性と型安全性を両立するために非常によく使われます。
共用体型は、APIレスポンス、フォーム入力、状態管理、関数の引数などで役立ちます。特に、文字列リテラル型と組み合わせることで、決まった候補だけを許可する型を作れます。これは、ステータスやモード管理に非常に便利です。
14.1 共用体型とは?
共用体型は、「この型またはこの型」という指定を行うための型です。たとえば、IDが数値の場合も文字列の場合もあるなら、number | stringと書けます。これにより、許可する型を限定しつつ、複数の形式に対応できます。
共用体型を使う場合は、値を使う前に型を絞り込むことが重要です。たとえば、string | numberの値に対して文字列メソッドを使うには、その値が文字列であることを確認する必要があります。TypeScriptはtypeofなどの条件分岐によって型を絞り込めます。
TypeScript
index.ts
let id: string | number;id = "user-001";id = 1001;
14.2 文字列リテラル型と組み合わせる
共用体型は、文字列リテラル型と組み合わせることで非常に便利になります。たとえば、ボタンの種類を"primary" | "secondary" | "danger"のように定義すれば、決められた文字列以外を受け付けない型を作れます。これにより、タイプミスを防ぎやすくなります。
ステータス管理でもよく使われます。たとえば、通信状態を"idle" | "loading" | "success" | "error"のように定義すると、状態の種類が明確になります。真偽値を複数使うよりも、状態が分かりやすくなることがあります。
TypeScript
index.ts
type Status = "idle" | "loading" | "success" | "error";const status: Status = "loading";
14.3 共用体型を使う場面
共用体型は、値が複数の候補を持つ場合に使います。ステータス、モード、種別、権限、APIレスポンスの成功・失敗、フォーム入力の型などが代表例です。anyを使うよりも許可する型を限定できるため、安全性が高くなります。
実務では、共用体型を使うことで、列挙型を使わずにシンプルな状態管理ができます。特に、Reactのコンポーネントのプロパティや状態管理では、文字列リテラルの共用体型がよく使われます。型の候補が少なく、文字列として扱いたい場合には非常に便利です。
15. リテラル型
リテラル型は、特定の値そのものを型として扱う仕組みです。たとえば、"admin"、"user"、100、trueのように、値そのものを型として指定できます。リテラル型は、共用体型と組み合わせて、許可する値を厳密に制限するためによく使われます。
リテラル型を使うと、状態や設定値のタイプミスを防ぎやすくなります。たとえば、"success"と書くべきところを"sucess"と間違えた場合、TypeScriptがエラーを出してくれます。決まった値だけを扱う場面では、単なるstringよりもリテラル型を使う方が安全です。
15.1 リテラル型とは?
リテラル型は、具体的な値だけを許可する型です。たとえば、type Direction = "left" | "right"と定義すれば、"left"または"right"以外の文字列は代入できません。これにより、値の候補を明確に制限できます。
リテラル型は、設定、状態、モード、種別などに向いています。単なる文字列型では自由すぎる場合に、リテラル型を使うと型安全性を高められます。特にUI開発では、ボタンサイズ、色、バリアント、表示モードなどを表すためによく使われます。
TypeScript
index.ts
type ButtonSize = "small" | "medium" | "large";const size: ButtonSize = "medium";
15.2 数値リテラル型
リテラル型は文字列だけでなく、数値にも使えます。たとえば、評価スコアを1から5の範囲だけにしたい場合、1 | 2 | 3 | 4 | 5のように定義できます。これにより、許可されていない数値を代入できなくなります。
ただし、数値の範囲が広い場合は、リテラル型で列挙するよりもバリデーションで制御する方が現実的です。数値リテラル型は、候補が少なく明確な場合に使うとよいでしょう。
TypeScript
index.ts
type Rating = 1 | 2 | 3 | 4 | 5;const rating: Rating = 5;
15.3 リテラル型を使う場面
リテラル型は、決まった選択肢だけを許可したい場合に使います。ボタンの種類、画面モード、APIのレスポンス種別、注文ステータス、ユーザー権限などが代表例です。単なるstringやnumberでは自由度が高すぎる場合、リテラル型を使うことで安全性を高められます。
特に、共用体型と組み合わせることで、列挙型の代わりとして使うことができます。小規模から中規模のTypeScript開発では、文字列リテラル型を使った状態管理が非常に実用的です。
16. 型推論
型推論とは、TypeScriptが代入された値から自動的に型を判断する仕組みです。たとえば、const name = "Taro"と書くと、TypeScriptはnameを文字列として推論します。明示的に: stringと書かなくても、型チェックや補完が効きます。
型推論はTypeScriptの大きな特徴です。すべての変数に型を書くと冗長になる場合がありますが、型推論を活用すれば、読みやすさを保ちながら型安全性を得られます。ただし、関数の引数や複雑なオブジェクト、外部に公開する型では、明示的に型を書く方が分かりやすい場合もあります。
16.1 型推論とは?
型推論は、TypeScriptがコードの内容から型を自動的に判断する機能です。文字列を代入すれば文字列型、数値を代入すれば数値型、真偽値を代入すれば真偽値型として扱われます。これにより、必要以上に型注釈を書かなくても安全なコードを書けます。
型推論を理解すると、TypeScriptのコードがより自然に書けるようになります。初心者はすべてに型を書きたくなることがありますが、明らかな場合は型推論に任せても問題ありません。一方で、関数の戻り値や複雑なデータ構造では、意図を明確にするために型を書くこともあります。
TypeScript
index.ts
const name = "Taro";const age = 25;const isActive = true;
16.2 明示的な型指定との使い分け
型推論と明示的な型指定は、どちらか一方だけを使うものではありません。単純な変数では型推論に任せ、関数の引数、戻り値、オブジェクトの構造、外部APIのデータなどでは明示的に型を書くとバランスが良くなります。
たとえば、const count = 10のような単純な変数では型注釈を省略しても問題ありません。しかし、関数がどのような値を返すべきかを明確にしたい場合は、戻り値の型を明示すると保守性が高まります。チーム開発では、型推論に任せる範囲と明示する範囲をルール化するとよいでしょう。
TypeScript
index.ts
function add(a: number, b: number): number { return a + b;}
16.3 型推論を使う場面
型推論は、初期値から型が明確な変数でよく使います。文字列、数値、真偽値、単純な配列などは、TypeScriptが正しく推論してくれるため、型注釈を省略しても読みやすい場合があります。これにより、コードがすっきりします。
ただし、空配列、空オブジェクト、外部データ、関数の戻り値などでは、意図しない推論になる場合があります。そのような場面では、明示的に型を指定することで安全性を高められます。型推論は便利ですが、常に意図通りになるとは限らないため、必要に応じて型注釈を使いましょう。
17. 基本型を使うときの注意点
TypeScriptの基本型を使うときは、型を細かく書けばよいというわけではありません。重要なのは、データの意味と利用目的に合った型を選ぶことです。たとえば、電話番号は数字で構成されていても計算しないため、数値型ではなく文字列型にする方が適切です。ステータスは単なる文字列ではなく、リテラル型や列挙型で候補を限定する方が安全です。
また、型は実行時のバリデーションを完全に代替するものではありません。TypeScriptの型チェックは主に開発時に行われるため、外部APIやユーザー入力から来るデータは、実行時にも検証する必要があります。型定義とバリデーションを組み合わせることで、より安全なアプリケーションを作れます。
17.1 任意型を多用しない
任意型は便利ですが、多用するとTypeScriptを使う意味が薄くなります。anyを使うと型チェックが弱くなり、存在しないプロパティや誤った操作を検出しにくくなります。結果として、実行時エラーが増える可能性があります。
どうしても型が分からない場合は、まずunknownを検討しましょう。unknownは型確認を行うまで値を使えないため、安全性を保ちやすくなります。anyは一時的な避難場所として使い、後で具体的な型に置き換えることが望ましいです。
17.2 文字列型を広くしすぎない
何でもstringで定義すると、タイプミスや不正な値を防ぎにくくなります。たとえば、ステータスをstringにすると、"success"だけでなく"sucess"のような誤った文字列も代入できてしまいます。決まった候補だけを許可したい場合は、文字列リテラル型を使う方が安全です。
実務では、ステータス、権限、モード、カテゴリなどは候補が決まっていることが多いです。このような値には、type Status = "success" | "error" | "loading"のような型を使うと、コードの安全性と可読性が向上します。
17.3 外部データは検証する
APIレスポンスやユーザー入力など、外部から入ってくるデータは、TypeScriptの型だけで安全とは言えません。TypeScriptの型はコンパイル時の情報であり、実行時に外部データが本当にその型であることを保証するものではありません。そのため、外部データを扱う場合は、型定義に加えて実行時の検証が必要です。
たとえば、APIからUser型のデータが返る想定でも、実際にはnameが存在しない可能性や、idが文字列になっている可能性があります。安全に扱うには、受け取ったデータを検証し、問題があればエラー処理を行う必要があります。TypeScriptとバリデーションを組み合わせることが、堅牢な開発につながります。
18. TypeScript基本型の使い分け
TypeScript基本型を使い分けるには、「値の種類」「値の意味」「値の候補」「値の信頼性」を考えることが重要です。文字列や数値のような単純な型だけでなく、リテラル型、共用体型、オブジェクト型、不明型を使い分けることで、より安全で読みやすいコードになります。
初心者は、まずstring、number、boolean、配列型、オブジェクト型を確実に理解しましょう。その後、unknown、void、never、共用体型、リテラル型を学ぶと、実務でよく使われる型定義を理解しやすくなります。anyは便利ですが、できるだけ避ける意識を持つことが大切です。
18.1 基本データにはプリミティブ型を使う
名前やメッセージには文字列型、価格や数量には数値型、有効・無効の状態には真偽値型を使います。これはTypeScriptの最も基本的な使い方です。値の種類に合った型を指定することで、コードの意図が明確になります。
ただし、数字の見た目をしていても計算しない値は文字列型にするなど、用途に応じた判断が必要です。型は値の形式だけでなく、値をどのように使うかを基準に選ぶと分かりやすくなります。
18.2 一覧データには配列型を使う
複数の値をまとめて扱う場合は配列型を使います。文字列の一覧ならstring[]、数値の一覧ならnumber[]、ユーザー一覧ならUser[]のように定義します。配列の要素型を明確にしておくことで、繰り返し処理や画面表示で型チェックが効きやすくなります。
実務では、APIから取得した一覧データを配列として扱うことが多くあります。配列の中身がどのような構造かを型で定義しておくと、表示処理や検索処理、フィルター処理を安全に書けます。
18.3 候補が決まっている値にはリテラル型を使う
ステータス、権限、モード、カテゴリなど、候補が決まっている値にはリテラル型や共用体型を使うと安全です。単なるstringでは不正な値も入ってしまいますが、リテラル型を使えば許可した値だけに制限できます。
たとえば、読み込み状態を"idle" | "loading" | "success" | "error"として定義すれば、状態の種類が明確になります。UI表示や条件分岐でも扱いやすくなるため、実務で非常に役立つ型です。
おわりに
TypeScript基本型は、TypeScriptを学ぶうえで最初に理解しておきたい重要な知識です。文字列型、数値型、真偽値型、配列型、タプル型、列挙型、任意型、不明型、戻り値なし型、到達不能型、オブジェクト型、共用体型、リテラル型などを理解することで、コードの安全性と読みやすさを大きく向上させることができます。
特に重要なのは、型を単なる文法として覚えるのではなく、データの意味に合わせて使い分けることです。名前やメッセージには文字列型、価格や数量には数値型、状態の有無には真偽値型、一覧データには配列型、構造を持つデータにはオブジェクト型、候補が決まっている値にはリテラル型や共用体型を使うと、より安全で分かりやすいコードになります。
また、anyを多用せず、型が不明な値にはunknownを使い、外部データは実行時にも検証することが重要です。TypeScriptの型は、開発中のミスを減らし、チームでコードの意図を共有しやすくするための強力な仕組みです。基本型をしっかり理解しておくことで、React、Next.js、Node.jsなどの実務的なTypeScript開発にもスムーズに進めるようになるでしょう。
EN
JP
KR