What it is and why to use it
A recursive conditional type can repeatedly unwrap a nested array type until it reaches a non-array element. infer captures the type inside the current array layer. This is useful when describing a transformation whose input may have several levels of nesting.
Common mistakes and limitations
Recursive types need a terminating case and can reach compiler depth limits. This example does not implement a runtime flattening algorithm, and tuple structure or union distribution may require a more specialised design.
Run this example
Use TypeScript 5.8 or later with strict checking and an ES2022 target. Save each complete example independently as example.ts, compile it, then run the generated JavaScript with a compatible Node.js installation. Compiler-only options below affect checking; they do not add runtime validation.
Terminal — compile and run
npx tsc example.ts --strict --target ES2022 --module commonjs
node example.jsSyntax
type ElementOf<T> = T extends ReadonlyArray<infer U> ? ElementOf<U> : T;Examples
Recursive Conditional Types for Nested Arrays
Standalone TypeScript 5.8+ example; expected output is explained below.
type ElementOf<T> = T extends ReadonlyArray<infer U> ? ElementOf<U> : T;
type Leaf = ElementOf<readonly (readonly number[])[]>;
const leaf: Leaf = 7;
console.log(leaf * 2);- The outer array yields readonly number[] as U.
- The next recursion unwraps that array to number, which is no longer an array and becomes the result.
- leaf is therefore numeric and doubling it produces 14. The type only derives a description; it does not flatten a real array.
- Expected output: 14
Best practices
- Recursive types need a terminating case and can reach compiler depth limits. This example does not implement a runtime flattening algorithm, and tuple structure or union distribution may require a more specialised design.
- Keep external-input validation separate from compile-time type descriptions.
Runtime & versions
Compiled to JavaScript. Feature availability depends on the language and runtime version used by your project; consult the official reference below.
TypeScript Handbook