2017-09-07 12 views
2

私は活字体でこの定数を作成する場合:TypeScriptで値の型を指定できますが、引き続きTSでキーの型を推測させることはできますか?

const PARAMS = { 
    green: {color: 0x007700}, 
    black: {color: 0x000000}, 
    white: {color: 0xffffff}, 
}; 

それは{ green: {color: number}; black: { color: number }; white: { color: number }; }ようなタイプを推論します。

しかし、値のタイプはTHREE.MeshBasicMaterialParametersである必要があります。

const PARAMS: {[name: string]: THREE.MeshBasicMaterialParameters} = { 
    green: {color: 0x007700}, 
    black: {color: 0x000000}, 
    white: {color: 0xffffff}, 
}; 

をその後私は、キーの特定可能性を失う(「緑」、「黒」又は「白」):私は、インデックス付きのタイプを使用してこれを宣言することができます。

const PARAMS: { 
    green: THREE.MeshBasicMaterialParameters, 
    black: THREE.MeshBasicMaterialParameters, 
    white: THREE.MeshBasicMaterialParameters 
} = { 
    green: {color: 0x007700}, 
    black: {color: 0x000000}, 
    white: {color: 0xffffff}, 
}; 

しかし、これはかなり冗長で繰り返しです。私はそれをより正確にモデル化することができます。

もっと簡潔にしたいタイプを手に入れる方法はありますか?

答えて

3

あなたは、一般的なマッピングされたタイプ

type ParamsType<Colors extends string> = { 
    [c in Colors]: THREE.MeshBasicMaterialParameters; 
} 

const PARAMS: ParamsType<'green' | 'black' | 'white'> = { 
    green: {color: 0x007700}, 
    black: {color: 0x000000}, 
    white: {color: 0xffffff}, 
}; 

を使用して冗長性を減らすことができますしかし、あなたはまだ二回色の名前を繰り返す必要があります。 typescriptでキーを推測するには、実行時に全く役に立たない中間関数を導入する必要があります。私はtypescriptを汎用パラメータを推論する他の方法についてはわかりません - there is a proposal on githubは、デフォルトのテンプレートパラメータの減算を許可しますが、それまでは何も実装されていませんでした。

function inferColorKeys<Colors extends string>(params: ParamsType<Colors>): ParamsType<Colors> { 
    return params; 
} 


const PARAMS = inferColorKeys({ 
    green: {color: 0x007700}, 
    black: {color: 0x000000}, 
    white: {color: 0xffffff}, 
}); 

UPDATE

@jcalzが示唆したようにあなたは、明示的なジェネリックパラメータを受け取り、その一般的なパラメータを推測する関数を返す関数にinferKeysを行うことによって、それは完全に汎用的にすることができます。関数には、いくつかの一般的なパラメータを明示的にも、推測的にも持たせることができないため、2つの関数でなければなりません。また、 type Record<K extends string, V> = {[k in K]: V}と定義されている組み込みのRecordタイプを使用します。

const inferKeys = <V>() => <K extends string>(x: Record<K,V>): Record<K,V> => x; 

const PARAMS = inferKeys<THREE.MeshBasicMaterialParameters>()({ 
    green: {color: 0x007700}, 
    black: {color: 0x000000}, 
    white: {color: 0xffffff}, 
}); 

PARAMSのタイプは

Record<"green" | "black" | "white", THREE.MeshBasicMaterialParameters> 
+0

私は 'inferColorKeys'トリックが好きです。それを一般的なものにすることは可能ですか? 'const PARAMS = inferKeys ({...});'と書いて、中間型を作成しないようにするには? – danvk

+1

関数がいくつかの一般的なパラメータを明示的にも、推測的にも持つことができないので、それほど簡単ではありません。バイパスする方法は、明示的な汎用パラメータを取るさらに別の中間関数を追加することですが、私が試してみると、その型の推論は、値型のための 'THREE.MeshBasicMaterialParameters'の代わりに' {color:number'}に戻ります。もっと考える必要がある。 – artem

+2

'const inferKeys = ()=>(x:Record )のようなものがあります:レコード => x;'? – jcalz

0

として、これはあなたのためのオプションです推察されますか?

const PARAMS = { 
    green: {color: 0x007700} as THREE.MeshBasicMaterialParameters, 
    black: {color: 0x000000} as THREE.MeshBasicMaterialParameters, 
    white: {color: 0xffffff} as THREE.MeshBasicMaterialParameters, 
}; 
+0

これは繰り返しですが、この問題も発生します:https://stackoverflow.com/questions/41964087/in-typescript-is-there-a-reason-to-prefer-const-foo-type-or-const-foo私はむしろ ':'より '' as ''を使うでしょう)。 – danvk

関連する問題