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

Jest自动Mock接口作用于Window/Element触发TS2589过深报错如何解决?

问题根因
  • 原MockedInterface类型无递归终止条件:string、number、boolean等原始值也会进入递归逻辑,遇到Element、Window这类存在自引用属性的内置类型时,会触发无限递归,最终抛出Type instantiation is excessively deep and possibly infinite.ts(2589)错误
  • 多余的类型交叉操作:& T[K]会额外增加TS类型计算开销,进一步拉长类型解析耗时
  • 无深度兜底逻辑:对于循环引用的结构没有停止递归的兜底机制,是触发报错的直接原因
修复后的实现
type JestMock<T, Y extends Array<any>> = (...args: Y) => T

export interface CalledWithMock<T, Y extends Array<any>> extends JestMock<T, Y> {
  calledWith: (...args: Y) => JestMock<T, Y>;
}

// 辅助类型:用于减少递归深度计数,可根据需要延长数组长度支持更深的递归
type Decrease<N extends number> = [never, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9][N];

// 泛型参数Depth可自定义递归深度,默认5层满足绝大多数Mock场景
export type MockedInterface<T, Depth extends number = 5> = 
  Depth extends 0 
    ? T 
    : T extends (...args: infer A) => infer B 
      ? CalledWithMock<B, A>
      : T extends object
        ? { [K in keyof T]: MockedInterface<T[K], Decrease<Depth>> }
        : T;
优化说明
  • 新增递归终止判断:非对象/函数的原始类型直接返回原值,避免不必要的递归计算
  • 新增深度兜底逻辑:默认最多递归5层,超过深度直接返回原类型,彻底解决循环引用导致的无限递归问题
  • 移除多余的交叉类型操作:CalledWithMock已经继承了原函数的调用签名,对象类型也会保留所有原属性,返回结果天然兼容原类型,无需额外交叉增加计算负担
  • 深度可自定义:如果有更深层级的Mock需求,可修改Depth默认值,或者延长Decrease类型的数组长度即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 12:45:03