抽象类实现的 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 的类型定义可以让我实现这个?
答案#1
使用一个返回具体实例作为映射值的函数。
更新:以下建议仅适用于 deno
作为建议,最好使用 Record 类型而不是 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();
语法 new() => AbstractFoo 定义了一个构造函数的签名,该构造函数不接受任何参数,并返回具有 AbstractFoo 结构的对象。
答案#2
据我所知,唯一可用的类型是 typeof AbstractFoo,也就是构造函数类型。就像 typeof Array 指的是 Array 构造函数的类型,而 Array 类型指的是数组实例的类型。
Both Concrete1 和 Concrete2 扩展了该类型(更准确地说,typeof Concrete1 和 typeof Concrete2 扩展了 typeof AbstractFoo)
但你不能创建如下地图:
const myMap: Map<string, typeof AbstractFoo> = new Map()
myMap.set('concrete1string', Concrete1)
myMap.set('concrete2string', Concrete2)
不,你可以,但 myMap.get('concrete1string') 的返回类型是 typeof AbstractFoo,而不是 typeof Concrete1。你不能用 new 调用 typeof AbstractFoo 类型的构造函数。
