TypeScript infer Keyword
The infer keyword is a powerful tool used within Conditional Types to declare a type variable that TypeScript will automatically deduce (infer) based on the type being checked.
It essentially allows you to say: "I don't know what this type is right now, but whatever it is, call it R so I can use it in the true branch."
1. Syntax
infer can only be used within the extends clause of a conditional type.
type MyType<T> = T extends SomePattern<infer U> ? U : Fallback;
2. Basic Example: Unpacking an Array
Suppose you have a type string[] and you want to extract string.
type UnpackArray<T> = T extends (infer U)[] ? U : T;
type T0 = UnpackArray<string[]>; // string
type T1 = UnpackArray<number[]>; // number
type T2 = UnpackArray<string>; // string (not an array, returns T)
Here, (infer U)[] matches the structure of T. If T is string[], then U is inferred to be string.
3. Recreating ReturnType
One of the most common uses is extracting the return type of a function. This is actually how the built-in ReturnType<T> utility is implemented.
type MyReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
function getUser() {
return { id: 1, name: "Alice" };
}
type User = MyReturnType<typeof getUser>;
// type User = { id: number; name: string; }
4. Extracting Promise Types
You can use infer to get the type inside a Promise.
type UnpackPromise<T> = T extends Promise<infer U> ? U : T;
type Res = UnpackPromise<Promise<string>>; // string
Recursive Unpacking:
If you have Promise<Promise<string>>, the above only unwraps one level. You can make it recursive:
type DeepUnpack<T> = T extends Promise<infer U> ? DeepUnpack<U> : T;
type DeepRes = DeepUnpack<Promise<Promise<number>>>; // number
5. Inference in Function Arguments
You can also infer types from arguments.
type FirstArgument<T> = T extends (first: infer A, ...args: any[]) => any ? A : never;
function greet(name: string, age: number) {}
type Name = FirstArgument<typeof greet>; // string
6. Multiple infer Declarations
You can use multiple infer keywords to extract different parts of a type.
type GetPair<T> = T extends [infer A, infer B] ? A | B : never;
type Union = GetPair<[string, number]>; // string | number
programming/javascript/typescript/typescript programming/javascript/typescript/conditional-types