识别打字稿中的接口和类之间的多态性

时间:2018-07-04 00:34:34

标签: javascript typescript oop interface polymorphism

我目前正在使用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 类型的含义的协议的一部分。

考虑到我期望的多态行为,我该如何编写接口,还是应该使用抽象类呢?我该如何处理这种多态行为?

1 个答案:

答案 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