【问题标题】:Typescript compiler won't allow methods on an union of two array types to be calledTypescript 编译器不允许调用两种数组类型联合上的方法
【发布时间】:2017-01-03 06:49:35
【问题描述】:

请考虑以下函数:

function getArray(): string[] | number[] {
    return [];
}

长话短说,当我这样做时:

getArray().forEach(item => console.log(item));

编译器给了我这个:

TS2349无法调用类型缺少调用签名的表达式。

为什么会这样?在我看来,forEach 应该可以在这里调用而不会出错,因为 as 就编译器而言,肯定会返回一个数组。有趣的是,IntelliSense 会像往常一样为此方法提供自动完成功能,但在使用自动完成建议后,错误消息将显示在输出中。

这是一个错误,还是我在这里遗漏了一些微不足道的东西?


编辑:我可以使用各种变通方法,例如返回 Array<string | number> 或使用重载,但我特别感兴趣的是为什么返回两个数组类型的联合不允许方法调用。

确定类型是数组,元素类型为string | number

【问题讨论】:

    标签: arrays typescript types


    【解决方案1】:

    您不能在 string[] | number[] 类型上调用 forEach

    你可能想要的是:Array<string | number>:

    function getArray(): Array<string | number> {
        return [];
    }
    
    var test = getArray().forEach(item => { console.log(item) }); // no error
    

    但如果您愿意,也可以转换为其中之一:

    (getArray() as string[]).forEach(item => { /* item is a string */ });
    

    或者你可以投到any:

    (getArray() as any[]).forEach(item => { /* item is any */ });
    

    【讨论】:

    • function getArray(): [string | number] { 也可以,原因相同。
    • [string | number] 是一个长度为 1 的元组,实际上并没有清楚地传达函数的意图!
    【解决方案2】:

    一般来说,没有一种很好的“安全”方法来处理联合类型的方法调用,其中方法具有不同的签名(TypeScript 允许在这些方法具有相同的签名时调用方法),就好像有只是一种方法。

    考虑这个例子:

    class ValueHaver<T> {
        value: T;
        update(x: () => T) { this.value = x(); }
    }
    
    let x: ValueHaver<number> | ValueHaver<string> = /*...*/;
    x.update(() => 42);
    

    此代码不正确。如果x 原来是ValueHaver&lt;string&gt;,那么您将有一个number 坐在string 应该在的位置。

    但此调用与forEach 调用Array&lt;number&gt; | Array&lt;string&gt; 一样有效(假设一些假设的规则集)。

    您可能会说“好吧,您可以尝试为联合中的每种可能的X 类型调用X.y 方法”。理论上这可以工作,但在实践中(尤其是在 TypeScript 2.0 中)你可以很容易地获得具有数十个成分的联合类型。 知道特定类型可以工作的唯一方法是重新检查整个调用,及其参数(因为上下文类型),这将是令人望而却步的昂贵的。并且由于技术原因,TS 编译器通常无法做到这一点——一旦给定表达式的类型被解析,它就会被缓存。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-19
      • 2021-10-21
      • 1970-01-01
      相关资源
      最近更新 更多