为什么我不能在union类型的变量上调用方法?

时间:2016-10-28 23:25:10

标签: typescript union-types

出乎意料的是,当我尝试在union类型的变量上调用方法时,我遇到了编译器错误。我已经隔离了这个问题,请参阅下面的代码。我想知道是什么阻止了编译器理解baz应该是string。是不是在编译器中没有实现(但是?)的某种边缘情况?或者这个代码是否有一些根本原因无效?

TypeScript版本:2.0.6

错误是:Cannot invoke an expression whose type lacks a call signature.

declare class A {
    foo(arg: number[] | number): string;
}

declare class B {
    foo(arg: number[]): string;
}

declare let bar: A | B;

let baz = bar.foo([3000]);

Playground

如果我在类A中使用方法重载而不是联合类型,它就会开始工作。但是,我的问题是真正的AB是在相对难以改变的第三方类型定义中定义的。

1 个答案:

答案 0 :(得分:2)

您可能希望bar.foo的类型为:

(arg: number[] | number) => string;

但实际上是这样的:

((arr: number | number[]) => string) | ((arr: number[]) => string)

这种类型确实无法调用。

如果您将B更改为:

declare class B {
    foo(arr: number[] | number): string;
}

然后错误就消失了(你可以明显改变A.foo以匹配B)。

修改

类型:

((arr: number | number[]) => string) | ((arr: number[]) => string)

不可调用,因为编译器没有引用应该调用哪些函数 如果它能够引用它,那么它将以(arg: number[] | number) => string类型开头。

当你执行此操作时它起作用的原因:

declare class A {
    foo(arg: number): string;
    foo(arg: number[]): string;
}

现在,A | B类型有一个共同的方法:foo(arg: number[]): string 因此,bar.foo的类型为(arr: number[]) => string,并且之前没有冲突。