TypeScript递归类型实例化过深问题的深层原因探究
TypeScript递归类型的深层实例化报错解析疑惑
初始报错场景
以下代码会触发「类型实例化过深」的报错:
type Type = [unknown] & { type: unknown }; interface $Zeros extends Type { // ~~~~~~ // Type instantiation is excessively deep... type: Zeros<this[0]> } type Zeros<N, R extends unknown[] = []> = N extends R['length'] ? R : Zeros<N, [0, ...R]>;
我原本推测问题出在this[0]为unknown时,TS尝试展开Zeros<unknown>,因条件类型的写法陷入无限递归。将条件判断翻转后报错消失,验证了这一点:
// 此实现无报错 type Zeros<N, R extends unknown[] = []> = R['length'] extends N ? R : Zeros<N, [0, ...R]>;
修改Type定义后的异常表现
但将Type改为对象形式的定义后,报错直接消失:
type Type = { 0: unknown, type: unknown }
甚至直接交叉类型查询也能正常工作:
type GetZeros = ($Zeros & [3])['type']; // 正常解析为[0,0,0]
提取apply类型后的复现问题
然而把逻辑提取到apply类型后,相同的报错又出现了(同样可通过翻转Zeros的条件解决):
type apply<$T extends Type, Args> = ($T & Args)['type']; type applyZeros = apply<$Zeros, [3]>; // ~~~~~~~~~~~~~~~~~~ // Type instantiation is excessively deep...
这里我感到困惑:原本以为this[0]会被推断为3,Zeros传入3后不会触发无限递归,但实际并非如此。显然我的认知模型存在偏差,想知道这背后的具体原因。
补充背景
以上是我在某个类型工具库中试验的两种简化设计。{ 0: unknown, type: unknown }的实现优势更多,是当前在用的方案,但[unknown] & { type: unknown }的报错行为更便于用户快速定位问题。在库的正常使用中,即使未传入参数,$Zeros['type']也会被其他类型查询以检查可组合性,因此处理this[0]为unknown时的无限递归问题至关重要。
内容的提问来源于stack exchange,提问作者geoffrey
相关产品推荐
相关产品推荐

