You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TypeScript函数中使用递归类型报深度超限错误如何解决?

问题1:你对报错原因的判断完全正确

TypeScript的递归类型校验触发时机分为两种场景:

  • 传入具体类型时,TS可以直接遍历到类型的终止节点,只要实际嵌套深度不超过默认的50层限制就不会报错
  • 传入未实例化的泛型时,TS无法预判泛型最终的实际嵌套深度,为了避免编译器陷入无限递归卡死,会在定义阶段就执行递归深度校验,一旦无法明确推导终止条件就会抛出你遇到的报错。

问题2:为什么TS不等待函数实例化再做校验

TypeScript的类型系统是设计为编译期静态校验的,泛型函数的合法性校验发生在函数定义阶段,要求函数逻辑对所有符合泛型约束的入参都合法,不可能将校验延迟到调用实例化阶段:

  1. 如果延迟到实例化阶段校验,会出现同一个函数定义,有的入参合法、有的入参触发类型错误的情况,不符合静态类型系统的设计原则
  2. 大量泛型函数延迟到调用时校验,会大幅提升编译期的性能开销,甚至出现大型项目编译卡死的问题

问题3:规避方案及最优解说明

你提到的通过计数限制递归深度确实是目前的最优解,没有其他更简单的方案可以绕开这个限制。

为什么你调整后的代码阈值超过10就报错

你印象中TS递归上限是50,这个数值是针对具体类型场景的限制,而泛型场景下的递归计数消耗要高很多:
你的递归类型每一层会做两次类型展开:

  1. 遍历keyof TRecord生成映射类型,每个key都要做一次条件判断
  2. 取[keyof TRecord]得到联合类型时,要对每个key的递归结果做合并推导
    相当于每层实际消耗的递归计数是你预期的2~3倍,再加上泛型场景下TS的递归阈值会比具体类型场景更严格,所以阈值设为10的时候就会触发上限。

如果需要处理更深的嵌套,可以把终止阈值调整到20~25,完全可以覆盖绝大多数业务场景的对象嵌套深度,也不会触发递归报错。你也可以改用更清晰的递减计数写法:

type MaxDepth = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
type AppendToTuple<T extends any[], U> = [...T, U] 
type NestedRecord = Record<string, any>

type RecursiveGetIndex<
  TRecord extends NestedRecord,
  TPreviousIndices extends any[] = [],
  TDepth extends number = 20
> = TDepth extends 0 ? TPreviousIndices : {
  [K in keyof TRecord]: TRecord[K] extends NestedRecord
    ? RecursiveGetIndex<
        TRecord[K],
        AppendToTuple<TPreviousIndices,K>,
        MaxDepth[TDepth]
      >
    : AppendToTuple<TPreviousIndices, K>
}[keyof TRecord]

内容的提问来源于stack exchange,提问作者sam256

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 19:36:03