【问题标题】:Typescript abstract class static method not enforced打字稿抽象类静态方法未强制执行
【发布时间】:2017-09-29 02:48:24
【问题描述】:

我在 TypeScript 中有这个简单的代码:

abstract class Config {
    readonly NAME: string;
    readonly TITLE: string;

    static CoreInterface: () => any
}

class Test implements Config {
    readonly NAME: string;
    readonly TITLE: string;
}

即使 Test 类中缺少 CoreInterface() 成员,TypeScript 也不会抱怨。为什么是这样?

我需要每个派生类在 CoreInterface() 静态函数中提供一些关于自身的元数据。我知道我可以扩展 Config 类并让每个子类提供自己的 CoreInterface() 实现,但我不希望子类自动继承 CConfig 类的任何成员.这就是为什么我使用“实现”而不是“扩展”

【问题讨论】:

  • 因为它不是会员。它是一个静态字段,因此属于类,而不是类的实例。
  • 那么有没有办法强制从 Config 派生的任何类都必须实现 CoreInterface()
  • 抽象类Config实现CoreInterface?这就是你想要的吗?
  • 你将如何表示CoreInterface()?您可以在这里发布您的解决方案的示例代码吗?
  • 实现一个接口的意思是:任何实现了Config的类的instance都会有这些实例字段和实例方法。由于 CoreInterface 是静态成员,因此无关紧要。静态成员属于类,而不是实例。而且它们不是多态的。如果您试图强制每个实现都必须具有给定的静态成员,那么 AFAIK,这是不可能的(而且我不明白它会起到什么作用)。你想达到什么目的?

标签: typescript interface static abstract-class static-typing


【解决方案1】:

根据您的评论,您可以通过以下方式实现您的目标:

interface ConfigConstructor {
    CoreInterface: () => any;
    new (): Config;
}

interface Config {
    readonly NAME: string;
    readonly TITLE: string;
}

const Test: ConfigConstructor = class Test implements Config {
    readonly NAME: string;
    readonly TITLE: string;

    static CoreInterface = function (): any { return "something"; }
}

(code in playground)

如果您注释掉其中一个成员(即:NAME),您将收到此错误:

“Test”类错误地实现了“Config”接口。
“测试”类型中缺少属性“名称”。

如果你注释掉静态的CoreInterface 你会得到这个错误:

类型“typeof Test”不可分配给类型“ConfigConstructor”。
“typeof Test”类型中缺少属性“CoreInterface”。


原答案

静态成员/方法不适用于继承(这通常适用于 OO,而不是特定于打字稿),因为(正如 @JBNizet 评论的那样)所有静态属性都属于类本身而不是实例。

Wikipedia article中所写:

即使不存在类的实例,也可以调用静态方法 然而。静态方法被称为“静态”,因为它们在 编译时间基于它们被调用的类而不是动态的 与实例方法一样,已解决 多态地基于对象的运行时类型。所以, 静态方法不能被覆盖

也可以查看这个帖子:Why aren't static methods considered good OO practice?

至于你想要完成的事情,你不会因为扩展类时没有实现静态方法而得到编译错误,但你会得到运行时错误:

class A {
    static fn() {
        throw new Error("not implemented!");
    }
}

class B extends A {
    static fn() {
        console.log("B.fn");
    }
}

class C extends A { }

B.fn(); // ok
C.fn(); // error: not implemented!

(code in playground)

【讨论】:

  • 您的回答提供了丰富的信息,但请记住,我并不想在这里进行继承(这就是我使用 implements 而不是 extends 的原因。另外, TypeScript 只是试图为 JavaScript 提供一些类型检查和智能感知,JavaScript 并不真正具有基于类的继承。因此,我正在尝试做的事情并不一定要映射到底层 JS;我只是想要一种方式表示一组类必须都具有某些特性。TypeScript 不能提供这种检查并没有真正的根本原因。
  • @prmph 好吧,它必须映射到底层 JS,因为它始终只是 JS。 TS 没有理由不能 这样做并不意味着它应该,因为它会破坏其对象模型(类似于许多其他对象模型)。跨度>
  • 检查我修改后的答案
  • @Dave:TypeScript 在发出 JS 时丢弃了很多类型信息;类型信息主要用于代码的静态分析,而不是运行时代码生成。
  • @Nizan Tomer:您的代码有效,太棒了!不过,我很好奇它为什么会起作用。我会假设 Test 中的 CoreInterface() 函数不必是静态的以满足 ConfigConstructor 接口,但它确实如此。它是如何工作的?
猜你喜欢
  • 2017-10-27
  • 2020-04-20
  • 1970-01-01
  • 2012-02-11
  • 2012-11-14
  • 2020-04-09
  • 2021-09-13
  • 2013-08-02
  • 2014-11-25
相关资源
最近更新 更多