"infer plus conditional plus mapped types is the full toolkit. Time to compose them."
What you already know
From track 8: infer declares a type variable inside a conditional pattern. T extends (infer R)[] ? R : T extracts the element type if T is an array. We covered the four canonical patterns: element-of-array, return-of-function, unwrap-promise, first-argument.
This lesson goes further: combining infer with mapped types, template literal types, and recursive patterns. These are the techniques behind most library type definitions you'll encounter.
Multiple infers in one pattern
You can declare multiple infer variables in the same pattern. T extends [infer A, infer B, ...infer Rest] ? [A, B, Rest] : never destructures a tuple into the first two elements plus the rest. Each infer captures a different piece.
Recursive type extraction
Conditional types can be recursive. type Flatten<T> = T extends (infer E)[] ? Flatten<E> : T recursively unwraps arrays. Flatten<string[][][]> evaluates to string. The recursion is bounded by the actual nesting depth — when T isn't an array anymore, recursion stops and returns T.
Template literal pattern matching
Combining infer with template literal types lets you pattern-match strings. T extends `${infer A}-${infer B}` ? [A, B] : never splits 'pippa-quest' into ['pippa', 'quest']. The infer captures the parts between the literal tokens.