TypeScript 无法对联合类型进行类型解析
TypeScript fails type resolution on union type
假设您有一些东西,可以是数字数组或字符串数组,并且您想映射到这个数组上。使用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.
你知道为什么会这样吗,或者这可能是编译器本身的问题?
您实际上看到的是第一种情况下的流量控制分析。由于您只为变量分配了一个数字数组,编译器将决定 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
至于为什么 map
不能在 string[] | number[]
的联合上调用,原因是 map
的类型将是 [= 中两个可用签名的联合类型14=] 和 number[]
签名不相同,它们之间不会发生合并。由于两个签名的联合是不可调用的,你会得到错误。
假设您有一些东西,可以是数字数组或字符串数组,并且您想映射到这个数组上。使用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.
你知道为什么会这样吗,或者这可能是编译器本身的问题?
您实际上看到的是第一种情况下的流量控制分析。由于您只为变量分配了一个数字数组,编译器将决定 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
至于为什么 map
不能在 string[] | number[]
的联合上调用,原因是 map
的类型将是 [= 中两个可用签名的联合类型14=] 和 number[]
签名不相同,它们之间不会发生合并。由于两个签名的联合是不可调用的,你会得到错误。