TSで特定のオブジェクトのプロパティをObject.keysで取得したいケースでちょっとハマったのでメモ書きとして残します。
目的はシンプルで、以下のようなHoge
型があったとします。
const Hoge = {
["aaaa"]: "A",
["bbbb"]: "B",
} as const;
このHoge
のキーをループで回した場合、通常は以下のように書くと思います。
Object.keys(Hoge).forEach((key) => {
console.log(Hoge[key]); // --> "A"とか"B"とかを表示
});
しかし、これだとエラーが出ます。 内容は下記の通りです。
TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ readonly aaaa: "A"; readonly bbbb: "B"; }'.
No index signature with a parameter of type 'string' was found on type '{ readonly aaaa: "A"; readonly bbbb: "B"; }'.
どうやらObject.keys()
はstring[]
を返すらしく、Hoge
のキーに合致しない可能性があるため当該のエラーが出ているようです。
どうにかしてObject.keys(Hoge)
のレスポンスはstring[]
ではなくHoge
のキー文字列のユニオン型の配列だと表現したいです。
Hoge
のkey
(あるいはvalue
)のユニオン型は以下のようにして作ることができます。
type HogeKeys = keyof typeof Hoge; // --> "aaaa" | "bbbb"
type HogeValues = typeof Hoge[HogeKeys]; // --> "A" | "B"
これを利用することで、先ほどのObject.keys
のレスポンスをstring[]
ではなくします。
// Object.keys(Hoge)をHogeKeys[]型とする
(Object.keys(Hoge) as (HogeKeys)[]).forEach((key) => {
console.log(Hoge[key]);
});
これでエラーが出なくなりました。
Typescript
は型付けができて非常に便利ですが、今回のようなケースやEnum
を絡めたようなケースだと型パズルにハマってしまうことがあります。
都度調べるしかないですが、今回の内容は色々と応用が効きそうなので備忘録として記事にしました。
今回の内容が役立ちましたら幸いです。