Javascript 在Typescript中识别接口和类之间的多态性

Javascript 在Typescript中识别接口和类之间的多态性,javascript,typescript,oop,interface,polymorphism,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中,情况似乎并非如此。我大致有以下设置: interfac

我目前正在使用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
someFunction()
的返回类型有问题,但根据我对多态性的理解,由于
B
实现
A
,如果函数返回
A
类型的内容,那么它也应该能够返回
B
类型的内容。话虽如此,有些东西“属于
A
”是没有意义的,因为接口不能实例化,只不过是类之间的无形协议或契约。因此,如果将
A
改为一个抽象类,那么多态行为的行为应该与我预期的一样,这似乎是合理的,但在我正在构建的库的范围内,
A
似乎更适合作为一个接口

编译器在声明
B
someFunction()
行中给出的问题如下:

部分问题似乎在于我在
a
中声明了一个构造函数。如果我删除了构造函数定义,问题就解决了,但我需要该定义成为协议的一部分,它从根本上说是
A
类型

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

我需要这个定义成为协议的一部分 基本上意味着属于A类

不幸的是,该语言不支持这一点。声明要实现的类
extends
只声明契约的实例部分,构造函数和静态方法是所谓的契约的一部分,并且没有办法为此声明契约

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

您使用的是哪个版本?我觉得很好。这种方法对我来说很好,你提到“编译器似乎有问题”。你能发布它产生的具体错误吗?@CRice我已经在我的帖子中添加了错误。让我知道这是否有助于进一步了解这种奇怪的行为。@mrmcgreg感谢您指出这个版本——事实证明,一个更新(我以前在2.4.2上)就足以解决一些问题。设置更像(更新了帖子以反映它),问题似乎出现在我在
a
中声明的构造函数中。非常感谢你!在更新了我的问题后,我意识到TypeScript手册中有一些关于这方面的材料,但你的回答让它更清楚了。目前,我已经切换到一个抽象类,而不是强制执行一些不同的类型要求,我意识到强调这些要求更有意义。
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