使用TypeScript从基类中的静态方法实例化子类

使用TypeScript从基类中的静态方法实例化子类,typescript,Typescript,作为TypeScript的新手,在实例化子类类型的基类中实现静态工厂的最佳方法是什么。例如,在基本模型类中考虑 FUNDALL < /代码>方法: class BaseModel { static data: {}[]; static findAll() { return this.data.map((x) => new this(x)); } constructor(readonly attributes) { } } class Model extends

作为TypeScript的新手,在实例化子类类型的基类中实现静态工厂的最佳方法是什么。例如,在基本模型类中考虑<代码> FUNDALL < /代码>方法:

class BaseModel {
  static data: {}[];
  static findAll() {
    return this.data.map((x) => new this(x));
  }
  constructor(readonly attributes) {
  }
}

class Model extends BaseModel {
  static data = [{id: 1}, {id: 2}];
  constructor(attributes) {
    super(attributes);
  }
}

const a = Model.findAll();  // This is BaseModel[] not Model[]

这将返回
BaseModel[]
而不是
Model[]

您需要将子类型构造函数传递给基类型上的静态函数

这是因为基类不知道(也不应该)知道子类型,以知道要使用哪个子构造函数

这是一个可能的示例-每个子类型定义自己的静态
findAll()
方法,该方法调用父类上的标准行为,传递数据和构造函数供父类使用:

class BaseModel {
    static data: {}[];

    static _findAll<T extends BaseModel>(data: any[], Type): T[] {
        return data.map((x) => new Type(x));
    }

    constructor(readonly attributes) {
    }
}

class Model extends BaseModel {
    static data = [{ id: 1 }, { id: 2 }];

    constructor(attributes) {
        super(attributes);
    }

    static findAll() {
        return BaseModel._findAll(this.data, this);
    }
}

const a = Model.findAll();
类基本模型{
静态数据:{}[];
静态_findAll(数据:任意[],类型):T[]{
返回data.map((x)=>新类型(x));
}
构造函数(只读属性){
}
}
类模型扩展了BaseModel{
静态数据=[{id:1},{id:2}];
构造函数(属性){
超级(属性);
}
静态findAll(){
返回BaseModel.\u findAll(this.data,this);
}
}
常数a=Model.findAll();

回答我自己的问题,这是TypeScript中一个众所周知的问题。Github问题有很长的讨论时间。解决办法如下:

导出类型StaticThis={new():T};
导出类基{
静态创建(this:StaticThis){
constthat=newthis();
归还;
}
baseMethod(){}
}
导出类派生扩展基{
derivedMethod(){}
}
//工作
Base.create().baseMethod();
派生的.create().baseMethod();
//也行
派生的.create().derivedMethod();
//不工作(正常)
Base.create().derivedMethod();

还有更好的方法。谢谢,我不知道静态函数的
新this()
功能我无法描述我花了多少时间来解决这个问题。谢谢dude@Tristan我刚刚遇到了一个棘手的情况,因为
Base
同时有一个通用的。。。想想看。。。出于好奇,指定T
扩展Base的目的是什么?我喜欢这个。当构造函数不接受参数时,它会工作,创建的更通用的签名是:
staticcreate(this:{new(…args:any[]):t;}
export type StaticThis<T> = { new (): T };

export class Base {
    static create<T extends Base>(this: StaticThis<T>) {
        const that = new this();
        return that;
    }
    baseMethod() { }
}

export class Derived extends Base {
    derivedMethod() { }
}

// works
Base.create().baseMethod();
Derived.create().baseMethod();
// works too
Derived.create().derivedMethod();
// does not work (normal)
Base.create().derivedMethod();