Advanced Patterns

infer keyword

The infer keyword declares a type variable within a conditional type's extends clause, extracting and capturing part of a type for use in the true branch.

Definition

TypeScript
type ElementType<T> = T extends (infer E)[] ? E : never;
type Unpacked = ElementType<string[]>; // string

Examples

Array Element Type
type ElementOf<T> = T extends (infer E)[] ? E : T;

type A = ElementOf<string[]>;  // string
type B = ElementOf<number[]>;  // number
type C = ElementOf<boolean>;   // boolean (not an array)
Promise Unwrapping
type UnwrapPromise<T> = T extends Promise<infer U> ? U : T;

type A = UnwrapPromise<Promise<string>>;  // string
type B = UnwrapPromise<Promise<number[]>>; // number[]
type C = UnwrapPromise<string>;           // string

type DeepUnwrap<T> = T extends Promise<infer U> ? DeepUnwrap<U> : T;
type D = DeepUnwrap<Promise<Promise<boolean>>>; // boolean
Function Signature Decomposition
type Head<T extends any[]> =
  T extends [infer First, ...any[]] ? First : never;

type Tail<T extends any[]> =
  T extends [any, ...infer Rest] ? Rest : never;

type A = Head<[1, 2, 3]>;  // 1
type B = Tail<[1, 2, 3]>;  // [2, 3]
type C = Head<[]>;          // never

Common Use Cases

  • 1Extracting element types from arrays and tuples
  • 2Unwrapping wrapper types like Promise, Observable, Ref
  • 3Decomposing function signatures into parameters and return
  • 4Tuple manipulation (head, tail, first, last)
  • 5Pattern matching on complex type structures

Understanding infer keyword

The infer keyword is TypeScript's mechanism for type-level pattern matching and extraction. It can only appear in the extends clause of a conditional type, where it declares a new type variable that captures part of the type being tested. If the condition matches, the captured type is available in the true branch.

The infer keyword is what makes utility types like ReturnType, Parameters, and InstanceType possible. ReturnType uses T extends (...args: any) => infer R to capture the return type R. Parameters uses T extends (...args: infer P) => any to capture the parameter tuple P. Without infer, these extractions would be impossible.

infer works with any structural position: array elements (T extends (infer E)[]), tuple positions (T extends [infer First, ...infer Rest]), promise values (T extends Promise<infer V>), function parts, and even template literal segments (T extends `${infer Prefix}.${infer Suffix}`).

Multiple infer variables can appear in a single conditional type. For example, you can simultaneously extract the parameters and return type: T extends (...args: infer P) => infer R. Each infer position captures independently.

Recursive types with infer enable powerful computations. A DeepUnwrap type that recursively unwraps nested Promises uses infer to peel off one layer at a time and then recurses on the result. Similarly, tuple manipulation types use infer with variadic tuple syntax to recursively process tuple elements.

TypeScript 4.7 introduced extends constraints on infer variables: infer E extends string restricts the inferred type to string subtypes. This is useful for template literal inference and other cases where you want to narrow the captured type.

Related Types

More Advanced Patterns

Explore TypeScript Types

Browse our complete reference of 30 TypeScript utility types with definitions, examples, and explanations.