TypeScript约束泛型函数调用类型差异原因咨询
TypeScript泛型约束中类型推断差异的原因分析
首先看定义的泛型函数及调用示例:
function getMinimum<T extends { length: number }>(arg1: T, arg2: T): T { if (arg1.length >= arg2.length) { return arg2; } else { return arg1; } } let str = "Hello world"; const res0 = getMinimum([1, 2, 3], str); // Argument of type 'number[]' is not assignable to parameter of type 'string' const res1 = getMinimum([1, 2, 3], {length: 12}); // res1 type - number[] | {length: number}
为什么两个调用的处理结果不同?
1. res0报错的本质原因
str通过let声明,TypeScript会自动将其类型拓宽为通用的string类型;而[1, 2, 3]的类型是number[]。
泛型函数要求两个参数必须属于同一个类型T(且T要满足extends { length: number }的约束)。此时TypeScript的类型推断逻辑是:
- 优先寻找一个单一类型来同时兼容两个参数,而非直接推断为联合类型。
string和number[]虽都符合{ length: number }的约束,但两者之间没有互相赋值的兼容性(字符串不能赋值给数组变量,数组也不能赋值给字符串变量),因此找不到这样的单一T,最终触发类型不匹配错误。
2. res1正常运行的原因
{ length: 12 }是匿名对象字面量,TypeScript会将其推断为{ length: number }类型;而[1, 2, 3]的类型是number[]。
这里TypeScript会将泛型参数T推断为number[] | { length: number }:
- 这个联合类型的每个成员都满足
extends { length: number }的约束,符合泛型的要求。 - 两个参数分别属于该联合类型的其中一个成员,因此类型检查通过,返回类型也被正确推断为这个联合类型。
补充:如果把str改成const声明?
若将str改为const str = "Hello world",其类型会被推断为字面量类型"Hello world"(而非通用string),但调用getMinimum([1,2,3], str)仍然会报错。原因是"Hello world"本质还是string的子类型,和number[]依然没有互相赋值的兼容性,TypeScript还是不会自动将T推断为联合类型。
内容的提问来源于stack exchange,提问作者Elton Lobo
相关产品推荐
相关产品推荐

