Advanced TypeScript

Conditional Types

Conditional types choose one type or another based on assignability. They are the foundation for many TypeScript utility types and library-level type transformations.
  • Conditional types are type-level branches
  • infer extracts part of a type
  • Naked type parameters distribute over unions
  • They are best for reusable type helpers
  • Type cleverness has maintenance cost
Extract awaited value
type AwaitedValue<T> = T extends Promise<infer U> ? U : T

type A = AwaitedValue<Promise<string>> // string
type B = AwaitedValue<number>          // number
`infer U` captures the value inside Promise<U>.
Distributive conditional type
type OnlyStrings<T> = T extends string ? T : never

type Result = OnlyStrings<string | number | "ok">
// string | "ok" simplifies to string
The conditional is applied to each union member.
Conditional type pieces
PieceMeaning
T extends UAssignability test
? A : BType-level branch
infer XCapture part of matched type
neverRemove impossible union branch
[T] extends [U]Prevent distributive behavior
Sources
  • The TypeScript HandbookConditional Types
  • Effective TypeScript, 2nd EditionType-level programming
  • TypeScript ReferenceConditional types