"infer captures a type from a pattern match. The compiler reads the shape and binds the slot."
What infer does
infer is a keyword used only inside the extends clause of a conditional type. It declares a type variable that captures part of the pattern being matched. T extends Array<infer E> ? E : never says: "if T is some Array<E>, set E to that element type; otherwise never."
This is the type-level version of destructuring. You write a pattern, and infer X is the binding that captures whatever was in that position.
The canonical uses
Element of array: type ElementOf<T> = T extends (infer E)[] ? E : never. Extract the array's element type.
Return type of function: type ReturnOf<F> = F extends (...args: any[]) => infer R ? R : never. The standard library's ReturnType is exactly this.
Promised type: type Unwrap<T> = T extends Promise<infer V> ? V : T. Extract the value from a Promise.
First argument: type FirstArg<F> = F extends (first: infer A, ...rest: any[]) => any ? A : never. Pull out the first parameter type.
Why infer matters
Without infer, you can check a type's shape (T extends Array<unknown>) but you can't get any new information out of it. infer is what turns conditional types from yes/no questions into pattern matches that bind variables. It's the difference between asking 'is it an array?' and asking 'what's the element type?'
This is the gateway to type-level programming. Once you can extract types from other types, you can compose them, transform them, and build sophisticated derived types — all without runtime work.
infer plus conditional types plus generics is the full toolkit for type-level computation. Most of the advanced TypeScript patterns in the wild are some combination of these three.