TypeScript Conditional Types
Conditional types let you compute a type based on a condition, using the T extends U ? X : Y syntax, enabling powerful type-level logic like filtering, unwrapping, and inference from other types.
Basic Conditional Type Syntax
A conditional type has the form T extends U ? X : Y, evaluated entirely at the type level: if T is assignable to U, the type resolves to X, otherwise to Y.
A simple conditional type
type IsString<T> = T extends string ? true : false;
type A = IsString<"hello">; // true
type B = IsString<42>; // falseDistributive Conditional Types
When T is a bare, naked type parameter in the condition, the conditional type distributes over a union, applying itself to each member separately and joining the results back into a union.
Distributing over a union
type ToArray<T> = T extends any ? T[] : never;
type StrOrNumArray = ToArray<string | number>;
// string[] | number[] (distributed member by member)Inferring Types With infer
The infer keyword, used inside the extends clause of a conditional type, captures part of the matched type as a new type variable, letting you extract things like a Promise's resolved value or an array's element type.
Extracting nested types
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;
type A2 = UnwrapPromise<Promise<string>>; // string
type B2 = UnwrapPromise<number>; // number
type ElementType<T> = T extends (infer U)[] ? U : never;
type Item = ElementType<number[]>; // number- Built-in utility types like ReturnType, Parameters, and Awaited are themselves built from conditional types plus infer
- Conditional types can filter members out of a union by resolving unwanted branches to never
- They power recursive helper types such as a DeepPartial or DeepReadonly
- They let a function's return type depend on the shape of its input type
Exercise: TypeScript Conditional Types
What is the basic syntax of a TypeScript conditional type?