infer Keyword
infer = "bhai, andar kya hai nikal ke bata!"
The infer keyword is used INSIDE conditional types to EXTRACT a type that's hidden inside another type. It's like saying "I don't know what type this is, but figure it out and give it a name so I can use it." Without infer, conditional types can only CHECK if a type matches a pattern. With infer, they can CAPTURE parts of that pattern and bring them into scope. This is what makes conditional types truly powerful.
Think of the undercover detective at the Hyderabad customs. A suspicious package arrives — you know it CONTAINS something, but you don't know WHAT. The detective opens the package, examines the contents carefully, and says "INFERRED: this contains gold biscuits!" The infer keyword is that detective — it peeks inside a type structure and names the hidden inner type.
T extends Promise<infer U> ? U : T — "If T is a Promise, figure out what type it resolves to and call it U. Then return U." The detective doesn't change the package — it just IDENTIFIES what's inside. infer can only be used in the extends clause of a conditional type — it can't exist on its own. It's a pattern-matching tool, not a standalone type declaration. Seedha samjho: infer = "bhai, andar kya hai nikal ke bata!" This single keyword unlocks some of the most advanced and useful type manipulations in TypeScript.
infer appears in the extends clause of a conditional type. The syntax is straightforward once you see it as a pattern-matching exercise: T extends SomeType<infer U> ? U : T. TypeScript checks if T matches the pattern, and if it does, it binds the matched part to the inferred name U.
Unwrapping Promises:
type UnwrapPromise<T> =
T extends Promise<infer U>
? U
: T;
type A = UnwrapPromise<Promise<string>>;
// A is string
type B = UnwrapPromise<number>;
// B is number (not a promise)
Unwrapping Arrays:
type UnwrapArray<T> =
T extends Array<infer U>
? U
: T;
type C = UnwrapArray<string[]>;
// C is string
Extracting Function Return Types:
type ReturnOf<T> =
T extends (
...args: any[]
) => infer R
? R
: never;
type D = ReturnOf<() => number>;
// D is number
type E = ReturnOf<
(x: string) => boolean
>;
// E is boolean
Extracting Function Parameter Types:
type FirstParam<T> =
T extends (
first: infer F,
...rest: any[]
) => any
? F
: never;
type F = FirstParam<
(x: string, y: number) => void
>;
// F is string
Each of these patterns follows the same structure: match a shape, use infer to name a hole in that shape, and then use the inferred name in the result.
Real-world TypeScript codebases use infer heavily, and TypeScript itself ships with several built-in utility types that rely on it. Understanding these patterns helps you read library code and write your own advanced type utilities.
1. ReturnType<F> — Built-in:
type R = ReturnType<typeof fetch>;
// The return type of fetch
// Promise<Response>
2. Parameters<F> — Built-in:
type P = Parameters<typeof fetch>;
// Tuple of fetch's parameter types
// [input: RequestInfo, init?: RequestInit]
3. Awaited<T> — Built-in (TS 4.5+):
type A = Awaited<
Promise<Promise<string>>
>;
// A is string (recursively unwrapped!)
4. Extracting from Constructors:
type InstanceOf<C> =
C extends new (
...args: any[]
) => infer I
? I
: never;
type T = InstanceOf<typeof Date>;
// T is Date instance type
5. Multiple infer Positions:
type UnpackFn<T> =
T extends (
a: infer A,
b: infer B
) => infer R
? { a: A; b: B; r: R }
: never;
type X = UnpackFn<
(x: string, y: number) => boolean
>;
// { a: string; b: number; r: boolean }
The infer keyword creates a BINDING — the inferred type is available in the true branch of the conditional. You can have multiple infer positions in a single conditional type, each capturing a different part of the pattern.
The infer keyword is incredibly powerful, but it comes with traps that can confuse even experienced TypeScript developers. Let's walk through the most common mistakes so you can avoid them in your code.
Trap 1: infer outside conditional type
// ERROR! infer can't exist alone
type X = infer U;
// RIGHT: inside extends clause
type X<T> =
T extends Promise<infer U>
? U
: T;
infer can ONLY appear in the extends clause of a conditional type. It's not a standalone keyword — it only makes sense when TypeScript is pattern-matching against a structure.
Trap 2: Multiple infer with same name
type X<T> =
T extends {
a: infer U;
b: infer U;
}
? U
: never;
// With { a: string, b: number }
// U = string & number = never!
If both a and b infer U, TypeScript INTERSECTS them! Use different names: infer A, infer B.
Trap 3: infer in the result branches
// ERROR! infer only in extends
type X<T> =
T extends string
? infer U
: never;
// RIGHT: infer in the condition
type X<T> =
T extends Promise<infer U>
? U
: never;
Trap 4: Nested generics — T extends Promise<Promise<infer U>> only unwraps TWO levels. For arbitrary nesting, use recursive conditional types like Awaited.
Trap 5: Extracting the wrong thing — ReturnType<(a: string) => void> gives void, not string! You extracted the RETURN type, not the parameter. Use Parameters for params.
Here's your complete cheatsheet for the infer keyword. Pin this to your mental whiteboard — it's the key to unlocking advanced type-level programming in TypeScript.
Syntax:
T extends SomeType<infer U>
? U
: Fallback;
Common Patterns:
// Unwrap Promise
Promise<infer U>
// Unwrap Array
Array<infer U>
// Function return type
(...args: any[]) => infer R
// Function first param
(first: infer F, ...rest: any[]) => any
// Constructor instance
new (...args: any[]) => infer I
Built-ins Using infer:
ReturnType<T>— function return typeParameters<T>— function params as tupleAwaited<T>— recursive Promise unwrapInstanceType<T>— constructor instance
Key Rules:
- infer = "andar kya hai nikal ke bata"
- Only works inside conditional type extends clause
- Multiple same-name infer = intersection
- Use different names for different positions
- Combine with recursion for deep unwrapping
The Golden Rule: infer is the undercover detective — it peeks inside types and names what it finds. Use it wisely, bhai, and it'll crack any type case!
Key Points
- infer extracts hidden types from inside other types — like a detective opening a package
- infer can ONLY be used in the extends clause of a conditional type
- Common patterns: unwrap Promise, Array, extract function return/params
- Multiple infer with the same name creates an intersection of all inferred types
- TypeScript built-ins like ReturnType, Parameters, and Awaited all use infer under the hood
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login