infer keyword
TypeScript · Reference cheat sheet
infer keyword
TypeScript · Reference cheat sheet
📋 Overview
infer introduces a type variable inside a conditional type’s extends clause. Use it to extract return types, element types, promise payloads, and pattern pieces from other types — the foundation of many utility types.
🔧 Core concepts
- Form —
T extends … infer U … ? True : False. - Scope —
Uis only usable in the true branch. - Multiple
infer— can appear several times; each binds independently. - Variance — position (covariant/contravariant) affects inference direction.
- Distributive — bare type params distribute over unions in conditionals.
💡 Examples
type ReturnOf<T> = T extends (...args: any) => infer R ? R : never;
type R = ReturnOf<() => Promise<number>>; // Promise<number>
type Awaited<T> = T extends PromiseLike<infer U> ? Awaited<U> : T;
type A = Awaited<Promise<Promise<string>>>; // string
type Head<T> = T extends [infer H, ...unknown[]] ? H : never;
type H = Head<[1, 2, 3]>; // 1
type Elem<T> = T extends (infer E)[] ? E : never;
type E = Elem<string[]>; // string
type PropType<T, K extends PropertyKey> =
T extends { [P in K]: infer V } ? V : never;
// Template + infer
type StripPrefix<S> = S extends `id-${infer Rest}` ? Rest : S;
type X = StripPrefix<"id-42">; // "42"
// Contravariant infer in parameters (simplified)
type FirstArg<T> = T extends (arg: infer A, ...rest: any) => any ? A : never;// Built-ins (prefer these): ReturnType, Parameters, Awaited, InstanceType
type RT = ReturnType<() => boolean>;
type P = Parameters<(a: string, b: number) => void>; // [string, number]⚠️ Pitfalls
inferonly works in conditionalextendsclauses, not arbitrary positions.- Distributive conditionals: wrap as
[T] extends […]to disable distribution. - Over-broad
anyin patterns weakens inference. - Recursive
infer/ conditionals can hit instantiation depth limits. - Prefer stdlib utilities when they already exist (
ReturnType, etc.).