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

TypeScript类型比较栈深度溢出问题:原因及解决方法

「Excessive stack depth comparing types」错误原因及解决方法

错误原因

  1. ReverseTuple递归无法正确终止:原定义中Rest的推断逻辑T extends [any, ...infer R extends [any, ...any[]]] ? R : never,在处理最后一个元素时无法将Rest收缩为终止状态,导致递归无限循环,超出TypeScript类型检查的栈深度限制。
  2. 多层嵌套递归叠加:compositor函数的类型约束嵌套了ReverseTuple<FunctionChainArray<ReverseTuple<T>>>,三层递归类型的叠加让类型计算复杂度指数级上升,直接触发栈溢出。
  3. 类型推断冗余复杂:FunctionChainArray中使用Lookup工具类型和多余的类型断言,加上映射类型与递归的结合,进一步增加了类型检查器的计算负担,加剧栈深度问题。

解决方法

1. 修复ReverseTuple的递归终止逻辑

调整Rest的推断方式,确保递归到单个元素时停止,避免无限递归:

type ReverseTuple<
  T extends [any, ...any[]],
  NewArray extends any[] = []
> = T extends [infer F, ...infer R] 
  ? R extends [] 
    ? [F, ...NewArray] 
    : ReverseTuple<R, [F, ...NewArray]>
  : NewArray;

2. 简化嵌套递归结构

减少compositor中的类型嵌套层数,将ReverseTuple和FunctionChainArray的组合逻辑扁平化:

type FunctionChainArray<T extends [Fn, ...Fn[]]> = {
  [K in keyof T]: K extends 0 
    ? (input: Parameters<T[K]>[0]) => ReturnType<T[K]>
    : (input: ReturnType<T[K-1]>) => ReturnType<T[K]>
} extends infer A ? A extends [Fn, ...Fn[]] ? A : never : never;

function compositor<T extends [Fn, ...Fn[]]>(
  ...functions: ReverseTuple<FunctionChainArray<ReverseTuple<T>>>
) {
  return functions as unknown as ReverseTuple<FunctionChainArray<ReverseTuple<T>>>;
}

3. 移除冗余类型工具

去掉Lookup这类多余的工具类型,直接使用数组索引访问简化类型计算。

修改后的完整代码

type Fn = (input: any) => any;

type ReverseTuple<
  T extends [any, ...any[]],
  NewArray extends any[] = []
> = T extends [infer F, ...infer R] 
  ? R extends [] 
    ? [F, ...NewArray] 
    : ReverseTuple<R, [F, ...NewArray]>
  : NewArray;

type LinkedFn<F1 extends Fn, F2 extends Fn> = (input: ReturnType<F1>) => ReturnType<F2>;

type FunctionChainArray<T extends [Fn, ...Fn[]]> = {
  [K in keyof T]: K extends 0 
    ? (input: Parameters<T[K]>[0]) => ReturnType<T[K]>
    : LinkedFn<T[K-1], T[K]>
} extends infer A ? A extends [Fn, ...Fn[]] ? A : never : never;

function compositor<T extends [Fn, ...Fn[]]>(
  ...functions: ReverseTuple<FunctionChainArray<ReverseTuple<T>>>
) {
  return functions as unknown as ReverseTuple<FunctionChainArray<ReverseTuple<T>>>;
}

const y2 = compositor(
  (a: 'Rb') => 'Rb' as 'Rb',
  (a: 'Ra') => 'Rb' as 'Rb',
  (a: 'start') => 'Ra' as 'Ra',
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 02:15:35