# 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.

```typescript
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`.

```typescript
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.

```typescript
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.

```typescript
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:

```typescript
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.

```typescript
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.

```typescript
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]]