【问题标题】:Recognizing Polymorphism Between Interfaces and Classes in Typescript识别 Typescript 中接口和类之间的多态性
【发布时间】:2018-12-12 08:20:58
【问题描述】:

我目前正在使用 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 { /* ... */ }
}

编译器似乎对BsomeFunction()的返回类型有问题,但是根据我对多态性的理解,因为B实现A,如果函数返回类型为A的东西,那么它也应该能够返回B 类型的东西。话虽如此,“类型为A”的东西是没有意义的,因为接口不能被实例化,并且只是类之间的无形协议或契约。如果 A 改为抽象类,那么多态行为应该像我预期的那样运行似乎是合理的——它确实如此——但在我正在构建的库的范围内,它似乎更适合 @987654339 @ 成为一个接口。

编译器特别给出的问题如下在声明BsomeFunction()的那一行:

[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

考虑到我期望的多态行为,我应该如何编写我的接口,或者我应该使用抽象类来代替?我如何带来这种多态行为?

【问题讨论】:

  • 您使用的是哪个版本?对我来说它看起来不错here。这种方法对我来说似乎很好。
  • 您提到“编译器似乎有问题”。你能发布它产生的具体错误吗?
  • @CRice 我在帖子中添加了错误。让我知道这是否能进一步阐明奇怪的行为。
  • @mrmcgreg 感谢您指出版本——事实证明,更新(我之前在 2.4.2 上)足以解决一些问题。设置有点像this(更新了帖子以反映它),问题似乎出在我在A 中声明的构造函数中。

标签: javascript typescript oop interface polymorphism


【解决方案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

【讨论】:

  • 明白。太感谢了!在更新我的问题后,我意识到 TypeScript 手册对此有一些材料,但你的回答让它更清楚了。目前,我已经切换到一个抽象类来代替强制执行一些不同的打字要求,我意识到强调这些要求更有意义。
猜你喜欢
  • 2020-05-19
  • 1970-01-01
  • 2017-04-19
  • 2019-07-03
  • 1970-01-01
  • 2021-08-28
  • 2013-03-29
  • 2016-12-05
  • 2018-06-23
相关资源
最近更新 更多