TypeScript Conditional Types Cheat Sheet
Covers the extends ? : syntax, infer keyword, distributive conditional types, and common utility type patterns built from them.
Basic Conditional Type Syntax
Conditional types select between two types based on an `extends` check, resolved at compile time.
type IsString<T> = T extends string ? true : false;type A = IsString<"hi">; // truetype B = IsString<42>; // falsetype Flatten<T> = T extends Array<infer Item> ? Item : T;type C = Flatten<string[]>; // stringtype D = Flatten<number>; // number (falls through)
Extracting Types with `infer`
`infer` introduces a type variable that TypeScript solves for within the conditional branch.
type ReturnOf<T> = T extends (...args: any[]) => infer R ? R : never;type Fn = () => Promise<string>;type R1 = ReturnOf<Fn>; // Promise<string>type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;type R2 = UnwrapPromise<Promise<number>>; // numbertype FirstArg<T> = T extends (arg: infer A, ...rest: any[]) => any ? A : never;type R3 = FirstArg<(id: string, name: string) => void>; // string
Distributive Conditional Types
Conditional types distribute over naked union types — a key gotcha and a key feature.
type ToArray<T> = T extends any ? T[] : never;type Result = ToArray<string | number>;// distributes: ToArray<string> | ToArray<number> => string[] | number[]// Wrap in a tuple to disable distribution:type ToArrayNonDist<T> = [T] extends [any] ? T[] : never;type Result2 = ToArrayNonDist<string | number>;// (string | number)[] — the union stays intact
Built-in Utility Types Using This Pattern
Standard library utilities that are just conditional types under the hood.
type Exclude<T, U> = T extends U ? never : T;type Extract<T, U> = T extends U ? T : never;type NonNullable<T> = T extends null | undefined ? never : T;type Status = "idle" | "loading" | "error" | "success";type Errored = Extract<Status, "error" | "success">; // "error" | "success"type NotErrored = Exclude<Status, "error">; // "idle" | "loading" | "success"
Common Conditional Type Patterns
Recipes you'll reuse across codebases.
- T extends U ? X : Y- core ternary form, evaluated per union member if T is naked
- infer- captures a subpart of T for use in the true branch
- [T] extends [U]- wraps in tuple to prevent distribution over unions
- T extends any ? T : never- forces distribution explicitly
- Awaited<T>- built-in recursive conditional type that unwraps nested Promises
- Parameters<T> / ReturnType<T>- infer-based extraction of function signatures
When a conditional type doesn't distribute the way you expect, check whether T is a 'naked' type parameter — distribution only happens when T appears alone on the left of extends, not wrapped in a tuple, array, or object.
Explore Topics
Professional Web Designing Services
- Responsive Websites
- E-commerce Solutions
- SEO Friendly Design
- Fast & Secure
- Support & Maintenance