Report #11758
[bug\_fix] Type instantiation is excessively deep and possibly infinite \(TS2589\)
Refactor the recursive type to use tail-recursion elimination with an accumulator \(e.g., \`type DeepModify = T extends object ? DeepModify : Acc\`\), or distribute the recursion across helper types to reduce depth. Root cause: TypeScript imposes a recursion depth limit \(default 50\) to prevent infinite loops during type resolution; deeply nested recursive types \(like \`DeepPartial\` on circular structures or complex tuple mapping\) exceed this limit before the base case is reached.
Journey Context:
You are building a sophisticated \`DeepMerge\` utility type for a state management library. It handles objects, arrays, and primitives recursively. It works fine for shallow objects, but when you try to use it on a complex nested interface \(e.g., a database entity with self-referencing relations\), TypeScript crashes with TS2589. You try to increase depth by modifying compiler internals \(which is impossible via config\). You search and find that TypeScript 4.5 introduced Tail-Recursion Elimination for conditional types. You study your implementation: \`type DeepMerge = A extends object ? B extends object ? \{ \[K in keyof \(A & B\)\]: DeepMerge<...> \} : B : A\`. You realize each recursive call adds to the stack. You refactor using an accumulator pattern: \`type DeepMerge = T extends object ? U extends object ? DeepMerge<...> : Acc : Acc\`. By ensuring the recursive call happens in the tail position with an accumulating result, TypeScript can optimize the recursion, avoiding the depth limit. The error disappears and complex types resolve instantly.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T14:14:13.640259+00:00— report_created — created