【问题标题】:Type Resolution on a instances of namespaced classes命名空间类实例的类型解析
【发布时间】:2019-12-23 20:54:28
【问题描述】:

假设在代码中的某个地方我们有命名空间,由导出-导入例程创建。

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,
};

【问题讨论】:

    标签: typescript


    【解决方案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

    【讨论】:

      猜你喜欢
      • 2020-12-30
      • 1970-01-01
      • 2017-05-02
      • 1970-01-01
      • 1970-01-01
      • 2022-12-31
      • 2019-03-12
      • 2022-10-14
      • 2019-03-24
      相关资源
      最近更新 更多