web-dev-qa-db-ja.com

マップされたタイプのインデックス署名を追加するにはどうすればよいですか?

私がインターフェースを持っているとしましょう

_interface X {
   a: string;
   b: number;
   c: boolean;
}
_

と機能

_function values(x: X) {
   return Object.keys(x).map(s => x[s])
}
_

TypeScriptのstrictフラグを有効にすると、「タイプ 'X'にはインデックス署名がないため、要素には暗黙的に 'any'タイプがあります」というエラーが表示されます。したがって、明示的にするために、Xの定義にインデックス署名を追加するだけです。

_[key: string]: any;
_

簡単なピーシー。


ただし、I Xが代わりにマップされた型になった場合:

_type X<T> = {
  [P in keyof T]: string;
}
_

そして私は機能を持っています

_function values<T>(x: X<T>) {
  return Object.keys(x).map(s => x[s])
}
_

インデックス署名はどこに追加すればよいですか? Object.keys(x).map(s => (x as any)[s])のような大雑把なことをすることなく、これを明示的にする方法はありますか?

11
Stuart

あなたはできる:

interface X {
    a: string;
    b: number;
    c: boolean;
    [key: string]: X[keyof X];
}

X[keyof X]の結果は(string | number | boolean)になります。これは、関数の戻り値が(string | number | boolean)[]になるため、anyよりもさらにうまく機能します。

両方の例で機能する別の方法は次のとおりです。

function values(x: X) {
    const keys = Object.keys(x) as (keyof X)[];
    return keys.map(s => x[s]);
}

きれいではありませんが、少なくとも(x as any)よりも多くのタイプがあります。

もちろん、それを一般的にすることもできます:

function values<T>(x: T) {
    const keys = Object.keys(x) as (keyof T)[];
    return keys.map(s => x[s]);
}
9
Meligy