`infer`

Pattern-Match and Extract a Type

`infer`

`infer` declares a type variable inside a conditional type's pattern. Used to extract types out of complex shapes.

4 min read Level 3/5 #typescript#infer#conditional-types
What you'll learn
  • Read `infer` in conditional types
  • Extract argument and return types from functions
  • Pull array element types

infer X declares a type variable inside a conditional type’s pattern. If the pattern matches, X is bound to the matched piece.

Extract Return Type

type ReturnTypeOf<T> = T extends (...args: any[]) => infer R ? R : never;

type A = ReturnTypeOf<() => string>;      // string
type B = ReturnTypeOf<(x: number) => User>; // User
type C = ReturnTypeOf<"not a function">;   // never

infer R binds R to whatever the function’s return type is.

Extract Parameter Types

type Params<T> = T extends (...args: infer A) => any ? A : never;

type P = Params<(a: string, b: number) => void>;   // [string, number]

Extract Array Element

type ElementOf<T> = T extends (infer U)[] ? U : never;

type E = ElementOf<string[]>;     // string
type F = ElementOf<User[]>;        // User

Extract Promise’s Resolution

type Awaited<T> = T extends Promise<infer R> ? R : T;

type A = Awaited<Promise<string>>;   // string
type B = Awaited<number>;             // number (not a Promise, T flows through)

A simplified Awaited<T> — the real one handles nested Promises.

Multiple infers

type FirstArg<T> = T extends (first: infer F, ...rest: any[]) => any ? F : never;
type LastArg<T> = T extends (...args: [...any[], infer L]) => any ? L : never;

infer in different positions extracts different pieces.

Built-In Utilities Use It

The standard library is full of infer:

  • ReturnType<T>
  • Parameters<T>
  • ConstructorParameters<T>
  • InstanceType<T>
  • Awaited<T>

Most of them are 3–6 lines using conditional types and infer.

Up Next

The subtle behavior of conditional types when T is a union.

Distributive Conditionals →