首页 > 解决方案 > 抽象类实现的 Typescript 类型声明

问题描述

我试图弄清楚如何提供与“实现某个抽象类的所有类”相对应的类型定义。以下面的代码示例为例:

abstract class AbstractFoo {
  abstract foo()
}

class Concrete1 extends AbstractFoo {
  foo() { ... }
}

class Concrete1 extends AbstractFoo {
  foo() { ... }
}

现在,我正在尝试创建一个从string一个具体类到其中一个的映射。请注意,我并不是要映射到具体类的实例中。请参阅以下内容:

const myMap: Map<string, typeINeedHelpWith> = new Map()
myMap.set('concrete1string', Concrete1)
myMap.set('concrete2string', Concrete2)

const instantiatedConcrete1 = new myMap.get('concrete1string')(...)

是否有一个类型定义typeINeedHelpWith可以让我完成这个?

标签: typescript

解决方案


使用将具体实例作为映射值返回的函数。

更新:以下建议仅对deno有效

作为建议,最好使用Record类型而不是 a Map,否则错误的键 ( mymap.get("concrete3")()) 将被视为运行时异常。

abstract class AbstractFoo {
    abstract foo(): number;
  }

  class Concrete1 extends AbstractFoo {
    foo() {
      return 1;
    }
  }

  class Concrete2 extends AbstractFoo {
    foo() {
      return 2;
    }
  }

  const myMap: Record<string, () => AbstractFoo> = {
    "concrete1": () => new Concrete1(),
    "concrete2": () => new Concrete2(),
  };

  const instantiatedConcrete1 = myMap.concrete1();

  let fooResult = instantiatedConcrete1.foo();

如评论中所述,请注意我使用了工厂模式来创建对象。

这被认为是一种很好的设计模式,但当不需要时,更简单的基于构造函数的解决方案可能更合适:

const myRec: Record<string, new() => AbstractFoo> = {
  "concrete1": Concrete1,
  "concrete2": Concrete2,
};

const iConcrete1 = new myRec.concrete1();

sintaxnew() => AbstractFoo定义了构造函数的签名,该构造函数不带参数并返回具有 shape 的对象AbstractFoo


推荐阅读