本文へスキップ
BecomeCoder

TypeScriptコース · 第7章 モダンTSと設定 · レッスン24

条件型と infer

ブラウザで完結

導入

「この型から、配列の要素の型だけを取り出したい」「関数の引数の型だけを取り出したい」といった、型そのものに対する条件分岐をしたいことがあります。条件型extends ? :)と infer を使うと、型の中から別の型を取り出せます。ライブラリの型定義を読むときによく登場します。

説明

条件型は T extends U ? X : Y の形で、「TU に当てはまるなら X、そうでなければ Y」という型を作ります。

type IsString<T> = T extends string ? "yes" : "no";

type A = IsString<string>;   // "yes"
type B = IsString<number>;   // "no"

let a: A = "yes";
let b: B = "no";
console.log(a, b);

infer を使うと、条件型の中で「型の一部を変数のように取り出す」ことができます。たとえば配列の要素の型を取り出す型はこう書けます。

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

type NumType = ElementType<number[]>;   // number
let n: NumType = 42;
console.log(n);

infer U は「T が配列なら、その要素の型を U として受け取る」という意味です。

やってみよう

type StrType = ElementType<string[]>; を追加し、let s: StrType = "文字列"; console.log(s); を試してみましょう。

演習

type FirstArg<T> = T extends (arg: infer A) => unknown ? A : never; という条件型を作ってください。function double(x: number): number { return x * 2; } があるとき、FirstArg<typeof double> で引数の型 ArgType を取り出し、ArgType 型の変数 v21 を入れて console.log(v * 2) で結果を表示してください。

ヒント1を見る

type FirstArg<T> = T extends (arg: infer A) => unknown ? A : never; と書きます。

ヒント2を見る

type ArgType = FirstArg<typeof double>; let v: ArgType = 21; console.log(v * 2);

実際に動かしてみよう

下のエディタにTypeScriptを書いて「実行」を押すと、その場でJavaScriptに変換してブラウザ内で実行し、出力が表示されます。本文の例をそのまま試したり、型注釈を書き換えたりしてみましょう(console.log の結果が下に出ます。初回だけコンパイラの読み込みに少し時間がかかります)。

TypeScript — ブラウザ内で実行

TypeScriptコンパイラ(同梱)でTS→JSに変換してから実行する学習用環境を読み込みます(初回のみコンパイラの読み込みに少し時間がかかります)。
スクロールして表示された時点でも自動で読み込まれます。