我目前正在使用 TypeScript(版本 2.9.2)开发一个项目,遇到了意外的多态行为。在 Java 和 C# 中,接口(interface)和类一样定义多态行为——也就是说,在下面,item1
可以是类型 A
因为它可以是 B
类型,而 item2
可以是 C
类型 因为它可以是类型D
:
interface A { }
class B implements A { }
class C { }
class D extends C { }
但在 TypeScript 中,情况似乎并非如此。我有大约以下设置:
interface A {
new (str: string): Module;
someFunction(str: string): A;
}
class B implements A {
constructor(str: string) { /* ... */ }
someFunction(str: string): B { /* ... */ }
}
编译器似乎对 B
的 someFunction()
的返回类型有问题,但根据我对多态性的理解,因为 B
实现了 A
,如果一个函数返回类型为 A
的东西,那么它也应该能够返回类型为 B
的东西。话虽如此,某些东西应该是“A
类型”是没有意义的,因为接口(interface)不能被实例化,并且只不过是类之间的无形协议(protocol)或契约。那么,如果 A
改为抽象类,那么多态行为应该如我所料——确实如此——但在我正在构建的库的范围内,这似乎是合理的A
更适合作为接口(interface)。
编译器特别给出的问题如下,声明B
的someFunction()
行:
[ts]
Property 'someFunction' in type 'B' is not assignable to the same property in base type 'A'.
Type '(str: string) => B' is not assignable to type '(str: string) => A'.
Type 'B' is not assignable to type 'A'.
Types of property 'someFunction' are incompatible.
Type '(str: string) => B' is not assignable to type '(str: string) => A'.
(method) Project.B.someFunction(str: string): B
部分问题似乎在于我在 A
中声明了一个构造函数。如果我删除该构造函数定义,问题就解决了,但我需要该定义成为A
类型的基本含义协议(protocol)的一部分。
考虑到我期望的多态行为,我应该如何编写我的界面,或者我应该使用抽象类来代替?如何实现这种多态行为?
最佳答案
I need that definition to be part of the agreement of what it fundamentally means to be of type A
不幸的是,该语言不支持该功能。 Construct signature can not be a part of contract声明要实现的类。 extends
仅声明合约的实例部分,构造函数和静态方法是所谓的 "static part" 的一部分。并且没有办法为此声明契约(Contract)。
TypeScript 使用结构类型,因此您实际上可以在需要指定构造签名的接口(interface)时使用 B
,但必须单独声明该接口(interface),并且每次都会检查一致性 B
就地使用,没有办法事先声明:
interface AConstructor {
new (str: string): A;
}
interface A {
someFunction(str: string): A;
}
class B implements A {
constructor(str: string) { /* ... */ }
someFunction(str: string): B { /* ... */ }
}
function f(cls: AConstructor) {
const instance = new cls('hi');
instance.someFunction('how are you?');
}
f(B); // ok
关于javascript - 识别 Typescript 中接口(interface)和类之间的多态性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51164402/