TS2589: Type instantiation is excessively deep and possibly infinite
A recursive conditional or mapped type is nesting too deeply for TypeScript's instantiation depth limit — usually from processing a large union, a deeply recursive utility type, or inferring across many chained generic calls. Add an explicit base case to stop the recursion, or simplify the type so TypeScript doesn't have to expand it so many levels deep.
What causes this error
TypeScript's type checker has a hard limit on how many levels deep it will recursively expand a conditional or mapped type before giving up, on the assumption that going further is either genuinely infinite or simply too complex to be worth resolving. Recursive utility types operating on large unions, deeply nested object shapes, or long generic call chains commonly hit this ceiling.
The Fix
// Prone to hitting the limit — recurses once per character in a long string type
type Reverse<S extends string> = S extends `${infer First}${infer Rest}`
? `${Reverse<Rest>}${First}`
: S;
// Fix — add an explicit depth-limited base case, or accept a coarser type
type Reverse<S extends string, Depth extends number[] = []> =
Depth['length'] extends 20 // stop after a reasonable depth
? string
: S extends `${infer First}${infer Rest}`
? `${Reverse<Rest, [...Depth, 0]>}${First}`
: S;Common causes / variations
- A recursive utility type with no depth guard, applied to very long strings, arrays, or deeply nested objects
- Excessively wide unions passed through a distributive conditional type
- Chaining many generic function calls where each return type feeds into the next as an inferred generic argument
Related errors
See also: TS2344 does not satisfy the constraint, TS2769 No overload matches this call.
Comments
Loading comments...