我目前正在使用TypeScript(版本2.9.2)进行项目开发,并且遇到了意外的多态行为。在Java和C#之类的系统中,接口定义多态行为的方式与类一样多—也就是说,在下面,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
的{{1}}的返回类型有问题,但是根据我对多态的理解,因为someFunction()
实现了B
,如果函数返回类型为A
的东西,那么它也应该能够返回类型为A
的东西。话虽这么说,因为“接口”不能被实例化,并且仅仅是类之间的无形协议或契约,所以某些东西应该“ B
类型”是没有意义的。这似乎是合理的,如果将A
改为一个抽象类,则多态行为应符合我的预期(确实如此),但是在我要构建的库的范围内,它似乎更适合A
成为界面。
在声明A
的{{1}}的行中,编译器特别提出的问题如下:
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
类型的含义的协议的一部分。
考虑到我期望的多态行为,我该如何编写接口,还是应该使用抽象类呢?我该如何处理这种多态行为?
答案 0 :(得分:1)
我需要该定义成为其定义的一部分 从根本上说是A型
不幸的是,该语言不支持该功能。 Construct signature can not be a part of contract声明要实现的类。 extends
仅声明合同的实例部分,构造函数和静态方法是所谓的"static part"的一部分,无法为此声明合同。
TypeScript使用结构化类型,因此实际上您可以在需要指定构造签名的接口时使用B
,但是必须单独声明该接口,并且每次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