2 min read

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