Conditional Types
Types that branch — choosing one type or another based on a compile-time relationship.
A conditional type is an if/else for types: T extends U ? X : Y. If T is assignable to U, the type resolves to X, otherwise Y.
type IsString<T> = T extends string ? "yes" : "no";
type A = IsString<"hi">; // "yes"
type B = IsString<42>; // "no"Distribution over unions
When the checked type is a naked type parameter and you feed it a union, the condition distributes over each member. ToArray<string | number> becomes string[] | number[], not (string | number)[]. Wrap both sides in a one-tuple — [T] extends [U] — to switch distribution off when you want the union treated as a whole.
Conditional types are how utility types like Exclude, Extract, and NonNullable are built.
Example
When to use it
- A utility type extracts the element type from an array type using a conditional to unwrap T[].
- A library conditional type converts a sync function type to an async one by inspecting the return type.
- A form helper uses conditional types to make only the fields matching a specific value type required.
More examples
Basic conditional type
A conditional type evaluates T extends string at compile time and selects true or false as the resulting type.
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false
type C = IsString<'hello'>; // true (literal extends string)Unwrap array element type
Uses infer to capture the element type E from an array type, returning never when T is not an array.
type ElementType<T> = T extends (infer E)[] ? E : never;
type A = ElementType<string[]>; // string
type B = ElementType<number[]>; // number
type C = ElementType<boolean>; // never (not an array)Distributive conditional type
When T is a union, the conditional distributes over each member, filtering out null and undefined to produce a clean type.
type NonNullable<T> = T extends null | undefined ? never : T;
type A = NonNullable<string | null | undefined>; // string
type B = NonNullable<number | null>; // number
Discussion