【问题标题】:How can I define a type that represents the subclass of an abstract class with static methods?如何使用静态方法定义表示抽象类的子类的类型?
【发布时间】:2021-04-16 22:41:02
【问题描述】:

如何定义作为另一个类的子类的类型(包括父类上的静态方法)?

简化示例

假设我有两个抽象基类和两个具体子类(每个子类一个):

abstract class BaseEntity {
  foo?: string;

  static init<T extends BaseEntity>(this: new () => T, data: Partial<T>): T {
    return Object.assign(new this(), data);
  }
}

class FooBarEntity extends BaseEntity {
  bar?: string;
}

abstract class BasePrinter<T extends BaseEntity> {

  constructor(
    private entityClass: typeof BaseEntity   // <-- This would work if BaseEntity weren't abstract.
                                             //     What should I do instead of this?
  ) {}
  
  initAndPrint(data: Partial<T>) {
    const entity = this.entityClass.init(data);

    console.log(entity);
  }
}

class FooBarPrinter extends BasePrinter<FooBarEntity> {
  // ...
}

目标

我希望能够做到这一点:

const myPrinter = new FooBarPrinter(FooBarEntity);

myPrinter.initAndPrint({ foo: 'FOO', bar: 'BAR' });    // FooBarEntity { foo: 'FOO', bar: 'BAR' }

我可以定义一个包含一个名为 initAndPrint 的函数的类型,但如果可以的话,我希望找到一种更通用/通用的方法。

【问题讨论】:

    标签: typescript typescript-typings typescript-generics


    【解决方案1】:

    也许您可以尝试使用泛型类型BaseEntityConstructor 来表示静态部分? (例如参见blog post

    如果你定义

    interface BaseEntityConstructor<T extends BaseEntity> {
      new (): T;
    
      init(this: new () => T, data: Partial<T>): T
    }
    

    并将BasePrinter 构造函数中的typeof BaseEntity 替换为BaseEntityConstructor&lt;T&gt;

    abstract class BasePrinter<T extends BaseEntity> {
      constructor(
        private entityClass: BaseEntityConstructor<T>
      ) {}
      ..
    }
    

    示例类型检查并运行正常。

    Playground Link

    【讨论】:

      【解决方案2】:

      所以我最终想出了这个:

      type ConstructorType<T = any> = new (...args: any[]) => T;
      
      type BaseEntityType<T> = ConstructorType<T> & {
        [K in keyof typeof BaseEntity]: (typeof BaseEntity)[K]
      }
      

      它基本上定义了一个通用的构造函数类型ConstructorType&lt;T&gt;,然后定义了它与 BaseEntity 上的静态属性的组合,以创建一个似乎按我预期的方式工作的类型。

      不确定是否有任何 egde 案例或我没有考虑的问题,但到目前为止它似乎有效。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-02
        • 1970-01-01
        • 2011-09-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多