让我们说一下在代码中我们有名称空间的地方,该名称空间是由export-import例程创建的。
namespace ClassCollection {
export class Test1 {
public Method1() { return 1; }
}
export class Test2 {
public Method2() { return 2; }
}
}
在主模块中的其他地方,我们要定义一个变量,该变量代表那些类的实例的字典。它的意思是通过循环遍历名称空间元素来自动完成,但是最后看起来像这样:
const collection = {
Test1: new ClassCollection.Test1,
Test2: new ClassCollection.Test2,
}
// to be accessible like this
collection.Test1.Method1();
collection.Test2.Method2();
每个类都可以轻松解决,就像这样:
const Test1: InstanceType<(typeof ClassCollection)["Test1"]>
= new ClassCollection.Test1;
const Test2: InstanceType<(typeof ClassCollection)["Test2"]>
= new ClassCollection.Test2;
Test1.Method1();
Test2.Method2();
但是如何为此进行通用类型解析?我最好的尝试是:
type TypeResolution<T> = {
[C in keyof T]: InstanceType<T[C]>;
};
/** won't work because of:
* Type 'T[C]' does not satisfy the constraint 'new (...args: any) => any'.
*/
const collection: TypeResolution<typeof ClassCollection> = {
Test1: new ClassCollection.Test1,
Test2: new ClassCollection.Test2,
};
答案 0 :(得分:1)
该错误告诉您T[C]
无法通过验证代表构造函数,因此TypeScript无法保证可以推断ClassCollection
命名空间中所有属性的实例类型。>
通过在通用类型参数T
上包含类型约束,可以告诉TypeScript实际上所有属性实际上都代表构造函数:
type TypeResolution<T extends Record<string, { new (...args: any[]): any }>> = {
[C in keyof T]: InstanceType<T[C]>;
};
现在,您可以为编译器提供足够的信息来计算实例类型and it all works correctly。