2017-08-10 9 views
0

データモデルを表す抽象クラスがあります。 Modelと呼んでみましょう。 ModelData型で実際にパラメータ化されています。これはモデルが実際に持つデータの種類を表します。したがって:Typescript:コンストラクタのハッシュ

export interface ModelData { type: string; attributes: {} } 
export class Model<D extends ModelData> {} 
export interface UserData extends ModelData 
    { type: 'users', attributes: { name: string; }} 
export class Users extends Model<UserData> {} 

問題はモデルコンストラクタのリポジトリを維持したいということです。私のデータストアが私に{ type: 'users', id: 1 }のような参照のリストを送ったとき、私はrefs.map(v => new ctors[v.type]({id: v.id}))かそのようなことをすることができるのが好きです。

問題は、私は、このオブジェクトは、サブクラスのコンストラクタの文字列のインデックス付きセットが含まれています」と宣言するのか分からないということである。

私は

private types: { [type: string]: typeof Model } 

、その後

find<T extends ModelData>(ref: ModelReference): Model<T> { 
    return new types[ref.type]({id: ref.id}) 
} 
を行うために使用

多かれ少なかれ(簡略化のため、ヌルガードとその他のコードは省略されています)

これは実際には正しくありません。私が実際に返すものはextends Model<T>です。タイプに格納されているものはtypeof Modelではなく、extends typeof Modelです。

2.4.1より前(暗黙的な一般的な変更に関係していると仮定します)、正しいコードではないにもかかわらず、コードをコンパイルしました。私はを作ることに満足していますが、私は実際にタイプスクリプトを使ってこれをどのように表現できるかはわかりません。

具体的には、ModelDataタイプのセットがあります。このタイプは、ModelDataの属性とリレーションシッププロパティとは異なるシェイプと、それぞれのModelDataタイプのModelを拡張するクラスのセットです。したがって、技術的にはモデルを返すことができますが、私はユーザーにいくつかの便利なメソッドを追加することができるので、ユーザーを返すことになります。

だから、それは 『「この事は、コンストラクタの文字列インデックスグループが含まれ、これらすべてのコンストラクタがパターンに従う』 AbstractClassを拡張し、言うことが可能である

答えて

1

私はのような何かをお勧めしたい:?

type Constructor<T> = { 
    new(...args: any[]): T; 
    readonly prototype: T; 
} 
const types = { 
    'users': Users, 
    // ... other Models 
} 

function find<K extends keyof typeof types>(ref: { type: K }): typeof types[K]['prototype'] { 
    return new types[ref.type](); // this only works if all Models have no-arg constructors 
} 

あなたはtypesは正しいことであることを確認する必要がある場合は、newキーワードを使用して、何かのコンストラクタを参照する方法があります私は「このオブジェクトはキーがModelData['type']値と同じである適切なModelタイプのコンストラクタである値を持っている」と言ってみたかった場合

、私が言うと思います:

type ModelMap<T> = { 
    [K in keyof T]: Constructor<Model<ModelData & { type: K }>> 
} 
function verifyTypes<T>(types: T, alsoTypes: ModelMap<T>) { } 
verifyTypes(types, types); 

verifyTypes()はあなたにコンパイラを与えた場合あなたのModelタイプは実際に右ModelDataタイプのいくつかのプロパティに保持している場合、コンパイラは唯一怒るだろうということ

const types = { 
    'user': Users 
} 
verifyTypes(types, types); // error: type of property 'user' is incompatible 

注:値のいずれかが悪いため、エラー、それはです。あなたの例が示すように、彼らが空の場合、すべてのあなたのタイプは、構造的に同一となり、コンパイラは文句を言うことはありません。助け

export class Model<D extends ModelData> { 
    data: D; // that's enough 
} 

希望。がんばろう!

+0

ええと、これは私が必要とするものに非常に近くなります。型変数をインスタンス変数として使用する方法はありますか? 'find 'を実行できますか? (それは箱から出なかった)。これにより、私のデータストアのサブクラスで実際の型を実際に定義することができます(データストアは汎用で、サブクラスは具体的なプロジェクト固有のデータ型を追加します) – pfooti

+0

'this [type ']の代わりに' this' 'しかし、私は' this'多型がこれを上回るかもしれないと思う。あなたのクラス名が 'DataStore'で' types'プロパティがある場合、 'typeof this.types'の代わりに' DataStore ['types'] 'を使うことができます。 – jcalz

関連する問題