TypeScript报错:类型参数'T'存在循环约束的原因排查
TypeScript循环约束报错原因及解决
先看你给出的报错代码:
type FuncHasArgumentsCheck<T extends (...args: any[]) => any> = T extends (...args: []) => any ? never // zero arguments : T; // Extracts the first argument type, or `never` if no arguments are found. type FuncFirstArgumentType<T extends FuncHasArgumentsCheck<T>> = T extends (first: infer TFirst, ...args: any[]) => any ? TFirst : never;
TypeScript提示Type parameter 'T' has a circular constraint.(2313),原因如下:
循环约束的本质
你在FuncFirstArgumentType的类型参数约束里写了T extends FuncHasArgumentsCheck<T>,这就形成了循环依赖:
- TypeScript要验证
T是否符合约束,必须先计算FuncHasArgumentsCheck<T>的结果 - 但
FuncHasArgumentsCheck<T>的计算完全依赖于T本身的类型 - 这种“用T的结果来约束T”的逻辑,被TypeScript判定为循环约束,因为它无法打破这个依赖链完成类型推导
解决方法
其实你的需求是提取函数的第一个参数类型,无参时返回never,完全不需要额外的FuncHasArgumentsCheck约束,直接简化即可:
type FuncFirstArgumentType<T extends (...args: any[]) => any> = T extends (first: infer TFirst, ...args: any[]) => any ? TFirst : never;
如果一定要强制约束传入的函数必须带至少一个参数,可以换一种非循环的约束写法:
// 先定义“带至少一个参数的函数”类型 type FuncWithAtLeastOneArg = (...args: [any, ...any[]]) => any; type FuncFirstArgumentType<T extends FuncWithAtLeastOneArg> = T extends (first: infer TFirst, ...args: any[]) => any ? TFirst : never;
补充说明
你觉得FuncHasArgumentsCheck不依赖FuncFirstArgumentType所以没问题,但问题出在约束本身的循环,而不是两个类型别名之间的依赖。TypeScript的类型约束要求约束表达式必须是可以独立于被约束参数计算的,你的写法违反了这个规则。
内容的提问来源于stack exchange,提问作者Serg
相关产品推荐
相关产品推荐

