TypeScript typings for Map
只支持Map<K, V>
,其中K
是键类型,V
是值类型,它们之间没有进一步的关联.因此,如果您只按原样使用Map
,就不能让TypeScrip编译器强制执行额外的约束.
根据我对您问题的理解,我理解您的限制是键应该是(可能是抽象的)构造函数类型,并且对于每个键,值应该是兼容类型的构造函数(必须是具体的).由于您的示例代码只使用set()
方法,因此使您的示例代码按所需方式运行的最少类型如下:
interface MySpecialMap {
set<T extends object>(
k: abstract new (...args: any) => T,
v: new (...args: any) => T
): this;
}
interface MySpecialMapConstructor {
new(): MySpecialMap;
}
const MySpecialMap: MySpecialMapConstructor = Map;
在这里,我将MySpecialMap
构造函数定义为运行时的Map
构造函数,但我为其指定了类型MySpecialMapConstructor
,该类型构造MySpecialMap
的实例.MySpecialMap
接口只有一个方法set()
,它在基类实例的类型T
中是generic.k
参数是T
个实例类型的possibly abstract
constructor,而v
参数是T
个实例类型的必须是具体的构造函数.
让我们演示一下它是否按预期工作:
abstract class BaseA { a() { } }
class ConcreteA1 extends BaseA { a1() { } }
class ConcreteA2 extends BaseA { a2() { } }
abstract class BaseB { b() { } }
class ConcreteB extends BaseB { b1() { } }
const map = new MySpecialMap();
map.set(BaseA, ConcreteA1); // ok
map.set(BaseA, ConcreteA2); // ok
map.set(BaseB, ConcreteB); // ok
map.set(BaseA, ConcreteB); // error
// Property 'a' is missing in type 'ConcreteB' but required in type 'BaseA'
map.set(BaseA, BaseA); // error
// Cannot assign an abstract constructor type to a non-abstract constructor type.
看上go 不错!
在此之后,您可能希望为get()
或所需的任何其他方法添加类似的类型.或者,您可能希望更改set()
的调用签名,以指定零参数构造函数或要强制实施的任何其他约束.但希望这能让你开始学习.
Playground link to code个