2017-07-15 98 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(); 
相關問題