Typescript定义子类映射并在运行时创建子类

时间:2018-05-14 06:04:40

标签: typescript

我有3个类定义A,B和C,其中B& C都扩展了抽象类A。

abstract class A {
  public name: string;

  constructor(name: string) {
    this.name = name;
  }

  abstract getName(): string;
}

class B extends A {
  getName(): string {
    return "B: " + this.name;
  }
}

class C extends A {
  getName(): string {
    return "C: " + this.name;
  }
}

我正在尝试在运行时创建一个抽象类的子类,如下面的代码所示。但是它会导致编译器错误:“无法创建抽象类的实例”

const classes: { [type: string]: typeof A } = {
  b: B,
  c: C,
};

function test(type: string, name: string) {
  if (!classes.hasOwnProperty(type)) {
    throw new Error(`Invalid type: ${type}`);
  }
  const _class = classes[type];
  return new _class("name");  // compiler error: Cannot create an instance of abstract class.
}

let x = test("b", "bob");
console.log(x.getName());

如果我将classes定义更改为{ [type: string]: typeof B | typeof C }则可行。

const classes: { [type: string]: typeof B | typeof C } = {
  b: B,
  c: C,
};

function test(type: string, name: string) {
  if (!classes.hasOwnProperty(type)) {
    throw new Error(`Invalid type: ${type}`);
  }
  const _class = classes[type];
  return new _class("name");
}

let x = test("b", "bob");
console.log(x.getName());

但是这样定义会很快增长,例如typeof B | typeof C | typeof D | typeof E | etc.有没有更优雅的方法来解决这个问题?

1 个答案:

答案 0 :(得分:3)

您可以将地图值键入为string输入并返回A的构造函数:

type AConstructor = new (name: string) => A;

const classes: { [type: string]: AConstructor } = {
  b: B,
  c: C,
};