2017-07-15 12 views
2

TypeScriptを初めて使用しているため、子クラスタイプをインスタンス化する基本クラスに静的ファクトリを実装する最適な方法は何ですか?例えば、ベースモデルクラスでfindAll方法を考えてみましょう。これはBaseModel[]いうよりModel[]返し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[] 

答えて

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(); 
関連する問題