TypeScript泛型从函数多参数的推断规则及调用绑定差异解析
TypeScript多参数函数的泛型类型推断问题
先看定义的泛型函数:
function is<T>(a: T, ...b: [T, ...T[]]): boolean { return b.every(_ => _ === a) }
两种调用的报错差异
- 调用
is(10, 'foo')时,报错提示:error TS2345: Argument of type 'string' is not assignable to parameter of type 'number' - 调用
is([1], 'foo')时,报错提示:error TS2345: Argument of type 'number[]' is not assignable to parameter of type 'string'
核心原因分析
TypeScript的泛型推断逻辑结合类型兼容性和错误报告策略导致了这两种差异:
1. is(10, 'foo')的推断逻辑
10是number基本类型,'foo'是string基本类型,二者不存在互相兼容的关系(既不能把number赋值给string,也不能反向赋值)。此时TypeScript会优先以第一个参数的类型作为泛型T的推断结果(number),随后检查剩余参数是否符合T类型,自然'foo'不符合,报错指向第二个参数。
2. is([1], 'foo')的推断逻辑
[1]是number[]引用类型,'foo'是string基本类型,二者同样没有互相兼容的路径:
- 若
T推断为number[],则'foo'无法赋值给number[]; - 若
T推断为string,则[1]无法赋值给string。
此时TypeScript的错误报告策略会选择其中一种推断路径输出错误,这里它选择了将T推断为string(基本类型在类型推断的优先级中略高于引用类型,或是错误报告的启发式策略导致),因此报错指向第一个参数不符合string类型。
内容的提问来源于stack exchange,提问作者Takodana
相关产品推荐
相关产品推荐

