TL;DR
SomeType extends OtherType ? TrueType : FalseType の形で、左の型が右の型に代入できれば前の型、できなければ後ろの型になる TypeScript の型。ジェネリクスと組み合わせて、入力の型から出力の型を決められる。
なぜ必要か
入力の型によって戻り値の型を変える関数は、オーバーロードでも書ける。しかし TypeScript のハンドブックによると、扱う型が増えるたびにオーバーロードの数は指数的に増える。条件型を使うと、型の選び方を 1 か所にまとめて書ける。
仕組み
true の分岐の中では、検査した型パラメータが条件の型に絞り込まれる。infer キーワードを使うと、true の分岐で使う型変数を条件の中で宣言し、型の一部を取り出せる。
型パラメータにユニオン型を渡すと、条件型はユニオンの各メンバーに分配される。Effective TypeScript 項目53 によると、分配が起きるのは条件に型パラメータがそのまま使われている(T extends ...)場合だけである。分配させたくないときは、extends の両側を角かっこで囲む。
例
type Flatten<T> = T extends Array<infer Item> ? Item : T
type A = Flatten<string[]> // string
type ToArray<T> = T extends any ? T[] : never
type B = ToArray<string | number> // string[] | number[]
type ToArrayNonDist<T> = [T] extends [any] ? T[] : never
type C = ToArrayNonDist<string | number> // (string | number)[]注意点
infer でオーバーロードされた関数の型を推論すると、最後のシグネチャから推論される。引数の型のリストからオーバーロードを解決することはできない。