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
type ElementType<T> = T extends (infer E)[] ? E : never;
type Unpacked = ElementType<string[]>; // stringExamples
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)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>>>; // booleantype 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<[]>; // neverCommon 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
Conditional TypesConditional types select one of two types based on a condition expressed as an extends clause, enabling type-level branching logic.
Parameters<T>Extracts the parameter types of a function type T as a tuple, enabling you to reuse a function's argument types elsewhere.
ReturnType<T>Extracts the return type of a function type T, enabling you to reuse a function's output type without manual duplication.
Awaited<T>Recursively unwraps the resolved type of a Promise or nested Promises, giving you the eventual value type.
More Advanced Patterns
Explore TypeScript Types
Browse our complete reference of 30 TypeScript utility types with definitions, examples, and explanations.