【问题标题】:TypeScript fails type resolution on union typeTypeScript 在联合类型上的类型解析失败
【发布时间】:2021-08-16 20:06:19
【问题描述】:

假设您有一个可以是数字或字符串数​​组的东西,并且您想要映射到这个数组。使用 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 as string[] &amp; number[]).map(e =&gt; console.log(e)); 。要么,要么使用类型保护。

标签: typescript union-types


【解决方案1】:

您实际上在第一种情况下看到了流控制分析。由于您只为变量分配了一个数字数组,因此编译器将确定 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的类型将是string[]number[]这两个可用签名的联合类型,签名是不相同,它们之间不会发生合并。由于两个签名的并集是不可调用的,因此您将收到错误消息。

【讨论】:

    猜你喜欢
    • 2019-12-14
    • 2018-02-28
    • 2019-03-26
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    • 2020-05-23
    • 1970-01-01
    相关资源
    最近更新 更多