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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 11:43:15