カテゴリ: TypeScript 更新日: 2025/12/12

TypeScriptの条件付き型(Conditional Types)とジェネリクスの活用をやさしく解説!初心者でも理解できる型の魔法

TypeScriptの条件付き型(Conditional Types)とジェネリクスの活用
TypeScriptの条件付き型(Conditional Types)とジェネリクスの活用

先生と生徒の会話形式で理解しよう

生徒

「先生、TypeScriptで条件によって型を変えることってできるんですか?」

先生

「良い質問ですね。TypeScriptには、条件に応じて型を変える“条件付き型(Conditional Types)”という仕組みがあります。」

生徒

「型にも“if文”みたいなことができるってことですか?」

先生

「まさにその通りです!if文が“値”の世界で条件分岐するのに対して、条件付き型は“型”の世界で分岐するんですよ。」

生徒

「型が条件で変わるって、なんだか難しそうです……」

先生

「大丈夫です!初心者の方でもわかるように、具体的な例で一緒に学んでいきましょう。」

1. 条件付き型(Conditional Types)とは?

1. 条件付き型(Conditional Types)とは?
1. 条件付き型(Conditional Types)とは?

TypeScriptの条件付き型とは、「もしある型が別の型を満たしているならA型、そうでなければB型」といった条件で型を切り替える機能です。型の世界でif文のような動きをする仕組みです。

基本の書き方は次のようになります。


T extends U ? X : Y

これは「TがUを継承(extends)しているならX型、それ以外ならY型」という意味になります。extendsは「TがUの一部かどうか」を判定します。

例えば、次のようなコードを見てみましょう。


type IsString<T> = T extends string ? "文字列です" : "文字列ではありません";

type A = IsString<string>;  // "文字列です"
type B = IsString<number>;  // "文字列ではありません"

この例では、IsStringという型が、「もしTがstringなら“文字列です”」という文字列型を返し、そうでなければ“文字列ではありません”を返します。つまり、型の世界でも条件判断ができるのです。

2. ジェネリクスと条件付き型の組み合わせ

2. ジェネリクスと条件付き型の組み合わせ
2. ジェネリクスと条件付き型の組み合わせ

条件付き型は単体でも便利ですが、ジェネリクス(Generics)と組み合わせるとさらに強力です。ジェネリクスは「型をパラメータとして受け取る仕組み」で、同じ関数やクラスでも柔軟に型を変えられる特徴があります。

次の例を見てみましょう。


function getValue<T>(value: T): T extends string ? string : number {
    if (typeof value === "string") {
        return value.toUpperCase() as any;
    }
    return 0 as any;
}

const result1 = getValue("hello"); // string型
const result2 = getValue(123);     // number型

この関数では、引数が文字列なら返り値はstring型、数字ならnumber型として扱われます。つまり、getValue()関数は入力の型によって返り値の型が自動的に変化します。

実際に出力結果を確認してみると、次のようになります。


HELLO
0

このように、ジェネリクスと条件付き型を組み合わせることで、「型に応じて結果を変える」ような柔軟な処理ができます。

3. 条件付き型の応用例:配列かどうかを判定する

3. 条件付き型の応用例:配列かどうかを判定する
3. 条件付き型の応用例:配列かどうかを判定する

次に、もう少し実用的な例として「渡された型が配列かどうか」を判定する型を作ってみましょう。


type IsArray<T> = T extends any[] ? "配列です" : "配列ではありません";

type C = IsArray<number[]>; // "配列です"
type D = IsArray<string>;   // "配列ではありません"

このIsArray型は、もし渡された型が配列(any[])なら「配列です」と判断し、そうでない場合は「配列ではありません」と返します。まさに型の世界のif文ですね。

4. 条件付き型で型を変換する(マッピング的な使い方)

4. 条件付き型で型を変換する(マッピング的な使い方)
4. 条件付き型で型を変換する(マッピング的な使い方)

条件付き型は、単に真偽を判定するだけでなく、型を別の形に変換するためにも使えます。例えば、配列型から中身の要素型を取り出すような処理です。


type ElementType<T> = T extends (infer U)[] ? U : T;

type E = ElementType<string[]>; // string
type F = ElementType<number>;   // number

infer(インファー)というキーワードを使うと、配列の中の要素型を「推論」して取り出すことができます。もし配列でなければ、そのままの型を返すようになっています。

このように条件付き型を使うと、「型の中身を取り出す」「特定の型に変換する」といった柔軟な型操作が可能になります。

5. 条件付き型を理解するコツ

5. 条件付き型を理解するコツ
5. 条件付き型を理解するコツ

条件付き型を理解するポイントは、「型にif文を書いている」とイメージすることです。プログラムの中でifを使うように、型の中でも「もし〜なら」という条件を立てることで、より安全で強力な型チェックができます。

たとえば、APIのレスポンスが文字列かオブジェクトかによって処理を変えたい場合など、条件付き型を使うとコードの安全性が高まり、エラーを防げます。

TypeScriptのジェネリクスと条件付き型を活用することで、現実のアプリケーション開発でも非常に柔軟で堅牢なコードを書くことができるようになります。最初は少し難しく感じますが、使いこなせると型の世界がぐっと広がります。

まとめ

まとめ
まとめ

条件付き型とジェネリクスを通して見えてきたTypeScriptの型の考え方

この記事では、TypeScriptの条件付き型とジェネリクスを組み合わせた使い方について、基礎から応用まで段階的に学んできました。条件付き型は、型の世界で「もし〜なら」「そうでなければ」という分岐を表現できる仕組みであり、TypeScriptの型システムを深く理解するうえで非常に重要な要素です。従来の型定義では難しかった柔軟な型表現が、条件付き型によって可能になります。

特に、ジェネリクスと組み合わせることで、関数や型定義が受け取る型に応じて返り値の型や構造を変えられる点は、TypeScriptならではの強みと言えます。入力の型と出力の型の関係を明確に表現できるため、コードの可読性と安全性が大きく向上します。これは、規模の大きなアプリケーションやチーム開発においても大きなメリットになります。

条件付き型で実現できる柔軟な型設計

条件付き型を使うことで、「特定の型かどうかを判定する」「配列かどうかを見分ける」「配列なら中身の要素型を取り出す」といった高度な型操作が可能になります。これらはすべて実行時の処理ではなく、コンパイル時の型チェックとして行われるため、実際の動作に影響を与えることなく、バグの混入を防ぐ役割を果たします。

inferを使った型の推論は、最初は少し難しく感じるかもしれませんが、「型の中身を一時的に変数として取り出す仕組み」と考えると理解しやすくなります。条件付き型は、単なる知識として覚えるのではなく、「どんな場面で使えるのか」を意識しながら触れることで、自然と身についていきます。

実務を意識した条件付き型とジェネリクスのサンプル


type ApiResponse<T> = T extends string
    ? { status: "text"; data: string }
    : { status: "object"; data: T };

function handleResponse<T>(value: T): ApiResponse<T> {
    if (typeof value === "string") {
        return { status: "text", data: value } as any;
    }
    return { status: "object", data: value } as any;
}

const res1 = handleResponse("メッセージ");
const res2 = handleResponse({ id: 1, name: "ユーザー" });

この例では、条件付き型を使って、APIレスポンスの型を入力データに応じて変えています。文字列が返ってくる場合とオブジェクトが返ってくる場合を型レベルで明確に分けることで、後続の処理でも安全にデータを扱うことができます。実際のWebアプリケーション開発でも、このような考え方は頻繁に使われます。

先生と生徒の振り返り会話

生徒

「条件付き型って、最初は難しそうだと思っていましたけど、型の世界のif文だと考えたら少し分かりやすくなりました。」

先生

「その理解はとても大切ですね。条件付き型は、型に対して判断を行うための仕組みなので、プログラムのif文と対応付けて考えると整理しやすくなります。」

生徒

「ジェネリクスと組み合わせると、入力に応じて返り値の型が変わるのが面白いです。関数が賢くなった感じがします。」

先生

「まさにその通りです。TypeScriptの型は、正しく使えばコードの意図をしっかり表現してくれます。条件付き型とジェネリクスは、そのための強力な道具です。」

生徒

「これからは、型エラーを直すだけじゃなくて、どういう型設計がいいのかも考えながら書いてみたいです。」

先生

「それができるようになると、TypeScriptの理解が一段深まります。少しずつでいいので、今回学んだ条件付き型を実際のコードで試してみてください。」

カテゴリの一覧へ
新着記事
New1
TypeScript
TypeScriptでパスエイリアスを設定する方法!baseUrlとpathsでコードをスッキリ整理
New2
JavaScript
JavaScriptのfor文の書き方を初心者向けにやさしく解説
New3
JavaScript
JavaScriptの関数でよくあるエラーとその解決法まとめ
New4
JavaScript
JavaScriptのイベント処理でよくあるエラーとその対処法
人気記事
No.1
Java&Spring記事人気No1
JavaScript
JavaScriptのインストール方法まとめ!Windows・Mac・Linux別にステップ解説
No.2
Java&Spring記事人気No2
JavaScript
JavaScriptのマウスイベントの使い方(click, mouseoverなど)
No.3
Java&Spring記事人気No3
JavaScript
JavaScriptのtoStringとString関数の違いを初心者向けに解説
No.4
Java&Spring記事人気No4
JavaScript
JavaScriptの純粋関数(pure function)と副作用の違いを理解しよう
No.5
Java&Spring記事人気No5
JavaScript
JavaScriptプログラムの実行方法まとめ!ブラウザ・Node.js・コンソールの使い方
No.6
Java&Spring記事人気No6
JavaScript
JavaScriptで文字列をforループで1文字ずつ処理する方法!初心者向け解説
No.7
Java&Spring記事人気No7
TypeScript
TypeScript学習におすすめの無料教材・リファレンスサイト【初心者向け】
No.8
Java&Spring記事人気No8
TypeScript
TypeScriptの始め方:開発環境の構築手順【初心者向け】