2017-07-15 157 views
2

作为TypeScript的新手,在实例化子类类型的基类中实现静态工厂的最佳方法是什么。例如,在一个基础模型类考虑findAll方法:从基类中的静态方法实例化子类,使用TypeScript

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[]

回答

1

为了回答我自己的问题,这在TypeScript中是一个众所周知的问题。 Github问题进行了长时间的讨论。解决方案如下:follows

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(); 
0

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

这是因为基类没有(也不应该)知道有关子类型的任何信息以知道使用哪个子构造函数。

这是它可能如何看一个例子 - 各亚型定义了它自己的静态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(); 
相关问题