2017-01-17 5 views
1

TypeScriptの最新バージョン(2.1)では、ジェネリッククラスのメソッド引数をジェネリック型のプロパティに制限できます。generic型をTypeScriptのkeyofのサブセットに制限することはできますか?

class Foo<TEntity extends {[key:string]:any}> { 
    public bar<K extends keyof TEntity>(key:K, value:TEntity[K]) { } 
} 

、現在型システム内のキーの値は特定のタイプのあるサブセットであることがさらにキー部を拘束することが可能ですか?

私が探しているのは、この擬似コードの行に沿ったものです。

class Foo<TEntity extends {[key:string]:any}> { 
    public updateText<K extends keyof TEntity where TEntity[K] extends string>(key:K, value:any) { 
     this.model[key] = this.convertToText(value); 
    } 
} 

EDIT

は明確化のために私は私が達成しようとしているかの詳細な例を追加しました。

Demo on typescriptlang.org

convertText

type object = { [key: string]: any }; 

class Form<T extends object> { 
    private values: Partial<T> = {} as T; 

    protected convert<K extends keyof T>(key: K, input: any, converter: (value: any) => T[K]) 
    { 
     this.values[key] = converter(input); 
    } 

    protected convertText<K extends keyof T>(key: K, input: any) 
    { 
     this.values[key] = this.convert(key, input, this.stringConverter); 
    } 

    private stringConverter(value: any): string 
    { 
     return String(value); 
    } 
} 

Type 'string' is not assignable to type 'T[K]'ことを言ってエラーになります。コンパイラはこれが

this.convert('s', 123, v => String(v)); 

と、これはなりません

this.convert('n', 123, v => String(v)); 

を動作することを伝えることができ

interface Foo { 
    s: string 
    n: number 
} 

私は私がキーにconvertText方法を制限することができます願って考えると

ここで、値はタイプstringで、キー・パラメーターのタイプの安全性を取得します。

+0

それはあなたが求めているものを完全には明らかではありません。あなたは 'TEntity'マップの値を参照していますか?またはキー?あなたはあなたの質問を編集し、それをどのように使用するかの例を挙げることができますか? –

+0

擬似コードは、私がどのように使用するかの例です。 TEntity [K]が文字列であると宣言されていないので、 'this.model [key]'に文字列を代入できないというエラーが発生します。 – opex

+0

いいえ、それを行う方法はありません。コンパイラは 'TEntity [K]'が文字列かどうかを知る方法がないので、値を 'any'に定義したので、どのようにコンパイラが知ることができますか? –

答えて

2

可能です(ここでは非クラスの例を使用します)。以下は、T[P]が文字列であることを保証します。

function convertText<T extends {[key in P]: string }, P extends keyof T>(data: T, field: P & keyof T) { 
    // ... 
} 

アイデアはPに推測されたフィールドのみにTの種類を絞り込み、この場合stringには、あなたが望む正確なタイプを設定することです。

テスト:

let obj = { foo: 'lorem', bar: 2 }; 
convertText(obj, 'foo'); 
convertText(obj, 'bar'); // fails with: Type 'number' is not assignable to type 'string'. 
+0

クラスでもうまくいきましたが、インターフェイスで動作させることができませんでした。クドス –

関連する問題