TypeScript在联合类型上失败了类型解析

时间:2018-03-19 14:15:49

标签: typescript

假设你有一些东西可以是数字或字符串数​​组,你想要映射到这个数组。使用打字稿,表达这种情况的以下方式都可以被类型检查器接受。

[1, 2].map(e => console.log(e));
let arr: string[] | number[] = [1, 2];
arr.map(e => console.log(e));

但是如果我们添加一个显式的静态类型转换,为了描述arr,编译器将以我们的方式抛出错误:

(arr as string[] | number[]).map(e => console.log(e)); 
// Cannot invoke an expression whose type lacks a call signature. 
// Type '(<U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]) | (...' has no compatible call signatures.

你知道为什么会这样,或者这可能是编译器本身的问题吗?

1 个答案:

答案 0 :(得分:2)

在第一种情况下,您实际上看到了流量控制分析的实际应用。由于您只为变量分配了一个数字数组,编译器将确定arr的实际类型为number[],并且它将与之一起运行,使map调用有效。如果您实际为变量分配了string[],并且编译器无法静态地决定实际采用哪个代码路径,那么您将收到与显式强制转换相同的错误:

declare var decider : boolean
let arr: string[] | number[] = decider ? [1, 2] : ['a', 'b'];
arr.map(e => console.log(e)); // Will be an error 

至于为什么mapstring[] | number[]的并集上不可调用,原因是map的类型将是来自{{1}的两个可用签名的联合类型}和string[]签名不相同,它们之间不会发生合并。由于两个签名的并集不可调用,因此您将收到错误。