我正在尝试创建一个泛型函数,该函数返回数组中的随机项,并使用Typescript 2.6.2正确转发类型信息。
function sample<T>(array: T[]) : T {
const index = Math.floor(Math.random() * array.length);
return array[index];
}
const obj1 = sample([1, 'a', Symbol('sym')]);
// const obj1: number | string | symbol
const obj2 = sample([1, 'a', Symbol('sym'), {}]);
// const obj2: {}
const obj3 = sample([1, 'a', Symbol('sym'), {a: 'a'}]);
// const obj3: number | string | symbol | {a: string}
obj1
和obj3
的类型签名很好,但由于某种原因,第二个示例中的空对象会导致obj2
的签名被{}
替换
obj2
的签名变为{}
?答案 0 :(得分:1)
在推断类型时,TypeScript会尝试查找表达式的最低公共子类型,通常是这样 导致联合类型。所以如果你有:
compute()
其中a,b和c分别为const x = [a, b, c]
,A
和B
类型,C
的感染类型为x
。
这正是A | B | C
和obj1
所发生的情况。但为什么obj3
的类型为obj2
:
答案是TypeScript具有结构类型,这意味着如果类型A具有类型{}
的所有属性,则B
的实例可分配给A
。
B
表示空对象类型,由于它没有成员,因此任何其他对象类型都是此类型的子类型。因此,感染类型
{}
实际上等于number | string | symbol | {}
。 (回想一下,当{}
是A | B
的子集时,A
为B
。