MediumAdvanced Types📖 Theory Question

What are conditional types and how do you use infer for type extraction?

💡

Hint

T extends U ? X : Y — use infer inside extends to capture and name a type for use in X or Y

Full Answer

Conditional types are TypeScript's equivalent of if-else for types. Combined with infer, they let you extract type information from complex types.

// Unwrap a Promise
type Awaited<T> = T extends Promise<infer U> ? Awaited<U> : T;
// If T is a Promise, extract what it resolves to and recurse
// Otherwise return T as-is

// Extract the element type of an array
type ArrayElement<T> = T extends (infer E)[] ? E : never;
type Elem = ArrayElement<string[]>; // string

// Extract return type
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;

// Extract the first parameter
type FirstParam<T> = T extends (first: infer F, ...rest: any[]) => any
  ? F
  : never;

type FP = FirstParam<(a: string, b: number) => void>; // string

Multiple infer in one conditional:

// Extract both key and value types from a Map
type MapTypes<T> = T extends Map<infer K, infer V>
  ? { key: K; value: V }
  : never;

type UserMap = MapTypes<Map<string, User>>;
// { key: string; value: User }

// Flatten one level of nesting
type Flatten<T> = T extends Array<infer E>
  ? E extends Array<infer Inner> ? Inner : E
  : T;

type Flat = Flatten<number[][]>; // number[]
💡 infer only works inside extends clauses of conditional types. Think of it as "if this type matches this pattern, capture the matched part as a new type variable".

More Advanced Types Questions

MediumWhat are mapped types and how do you use them beyond the built-in utility types?MediumWhat are template literal types in TypeScript?

Practice this in a timed sprint →

5 free questions, no signup required

⚡ Start Sprint