型レベルの条件分岐
条件型の式で型に応じた分岐を行います。
「型レベルの条件分岐」はCoddyKit上の無料TypeScript Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはTypeScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 TypeScript Academyコースには全4レッスンが含まれています。
型レベルの if
型言語は、条件型によって分岐を獲得します。T extends U ? X : Y という構文は、「T が U に代入可能なら結果は X、そうでなければ Y」と読みます。
これは、if / else 式に相当する型レベルの仕組みです。
type IsString<T> = T extends string ? "yes" : "no";
type A = IsString<string>; // "yes"
type B = IsString<number>; // "no"extends は代入可能性を表す
このテストは等価性を調べるものではありません。T extends U は、型 T の値を、型 U が期待される場所で使える場合に真になります。リテラル型は、その基底型に代入可能です。
type T1 = "hello" extends string ? true : false; // true
type T2 = string extends "hello" ? true : false; // false
type T3 = 42 extends number ? true : false; // true結果の型を選ぶ
条件型を使うと、入力に応じて1つのジェネリックから異なる形を返せます。ここでの Wrap は、配列とスカラーを異なる形でラップします。
type Wrap<T> = T extends unknown[]
? { list: T }
: { value: T };
type A = Wrap<number>; // { value: number }
type B = Wrap<string[]>; // { list: string[] }never によるフィルタリング
よく使われる手法は、一方の分岐で never を返すことです。never は「値が存在しない」ことを意味し、後でユニオンからメンバーを取り除くのに便利です。
type OnlyStrings<T> = T extends string ? T : never;
type A = OnlyStrings<string>; // string
type B = OnlyStrings<number>; // neverinfer による推論
infer キーワードを使うと、本当の力が現れます。条件型の中で infer を使うと、新しい型変数が導入され、照合した型の一部を取り出せます。
ここでは、配列の要素型を取り出しています。
type ElementType<T> = T extends (infer U)[] ? U : never;
type A = ElementType<number[]>; // number
type B = ElementType<string[]>; // string関数の結果を推論する
パターンのどこにでも infer を配置できます。関数の戻り値の型を取り出すには、矢印の後ろの部分を推論します。組み込みの ReturnType はこのように動作します。
type MyReturn<T> = T extends (...args: any[]) => infer R ? R : never;
type A = MyReturn<() => number>; // number
type B = MyReturn<(x: string) => boolean>; // boolean複数の部分を推論する
1つの条件型で、複数の infer 変数を同時に導入できます。ここでは、タプルの先頭と残りの部分を両方取り出しています。
type FirstRest<T> = T extends [infer H, ...infer R]
? { head: H; rest: R }
: never;
type A = FirstRest<[1, 2, 3]>;
// { head: 1; rest: [2, 3] }条件型のネスト
条件型は、連続した else if と同じようにネストできます。ある条件型の else 分岐自体を別の条件型にすることで、段階的な判断の流れを作れます。
type Describe<T> =
T extends string ? "text" :
T extends number ? "num" :
T extends boolean ? "flag" :
"other";
type A = Describe<number>; // "num"
type B = Describe<null>; // "other"条件をガードとして使う
条件型を使って、そこから値を取り出す前に形状を検証できます。入力が一致しない場合は never にフォールバックすることで、誤用を明確にできます。
type GetName<T> = T extends { name: infer N } ? N : never;
type A = GetName<{ name: string }>; // string
type B = GetName<{ age: number }>; // never条件を組み合わせる
条件型をネストすると、複数の条件を要求できます。ここでは、ある型がオブジェクトであり、さらに id を持っていなければ通過できません。
type RequireId<T> =
T extends object
? T extends { id: unknown } ? T : never
: never;
type A = RequireId<{ id: 1; x: 2 }>; // { id: 1; x: 2 }
type B = RequireId<{ x: 2 }>; // never条件型は至るところにある
組み込みユーティリティ型の多くは、内部では条件型です。NonNullable、Extract、Exclude、Parameters、ReturnType などがあります。extends ? : を理解すれば、これらすべてを使いこなせます。
type MyNonNullable<T> = T extends null | undefined ? never : T;
type A = MyNonNullable<string | null>; // string理解度チェック
条件型と infer について、理解度を確認しましょう。
まとめ
条件型によって、型言語に if/else とパターンマッチングが加わります。
T extends U ? X : Yは、代入可能性に基づいて分岐します。inferは、照合した部分を新しい変数に取り込みます。- 条件型をネストして、段階的な判断の流れを作れます。
neverを返すことで、メンバーをフィルタリングできます。
次は、条件型を自分自身に再び適用する再帰です。
よくある質問
「型レベルの条件分岐」レッスンは無料ですか?
はい。「型レベルの条件分岐」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、TypeScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 TypeScript Academyコースには全4レッスンが含まれています。
「型レベルの条件分岐」で何を学びますか?
条件型の式で型に応じた分岐を行います。 ブラウザで直接実行するハンズオンコードでTypeScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
TypeScript Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのTypeScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「型レベルの条件分岐」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このTypeScript Academyレッスンでコードを書いて実行できますか?
はい。すべてのTypeScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。