What does the infer keyword do in a conditional type?
infer declares a type variable inside the extends clause of a conditional type, letting TypeScript capture part of the matched type. ReturnType is written as T extends (...args: any) => infer R ? R : never.
Explain it simply
Think of pattern matching with a wildcard. You tell TypeScript: "if the type looks like this shape, tell me what is in this blank spot". infer R is the name you give that blank.
You can only use infer in the extends part of a conditional type, and the captured name is usable in the true branch. It is how you pull element types out of arrays, resolved values out of promises, and arguments out of functions.
Example
// Reimplement ReturnType
type MyReturn<T> = T extends (...args: any[]) => infer R ? R : never;
type R1 = MyReturn<() => string>; // string
// Element type of an array
type ElementOf<T> = T extends (infer E)[] ? E : never;
type E1 = ElementOf<number[]>; // number
// Value inside a Promise
type Unwrap<T> = T extends Promise<infer V> ? V : T;
type U1 = Unwrap<Promise<boolean>>; // boolean
type U2 = Unwrap<string>; // string
// First function argument
type First<T> = T extends (a: infer A, ...rest: any[]) => any ? A : never;
type F1 = First<(x: number, y: string) => void>; // numberWhat to say in the interview
"infer lets me capture a piece of a type inside a conditional type's extends clause, like the return type of a function or the element of an array. Built-ins such as ReturnType, Parameters and Awaited are all written with it."
Common mistakes
- Using infer outside the extends clause; it is only valid there.