TypeScript ループ内でオブジェクトのプロパティに変数を使ってアクセスしたい場合
CSSをtsで直書きしようとした際に問題発生。
スタイル指定をオブジェクトにしてループまわし、
要素.style[prop]
でアクセスしようとしたが、以下エラー。
インデックス式が型 'number' ではないため、要素に 'any' 型が暗黙的に指定されます。
propに型アサーションをくわえるとエラーが消えた。
propに入りうる値に合致する文字列リテラル型(のユニオン型)を指定するとエラーが出ないみたい。
document.querySelectorAll<HTMLElement>('.box').forEach(($el) => { const sobj = { background: '#00f', color: '#fff', padding: '1em', margin: '0.5em 0' } Object.entries(sobj).forEach(([prop, val]) => { // $el.style[prop] = val //インデックス式が型 'number' ではないため、要素に 'any' 型が暗黙的に指定されます。 $el.style[prop as keyof typeof sobj] = val // prop as "background" | "color"... }) })
typeof, keyof
いずれも型情報を取得する
typeof obj
でobjから型を取得( jsで型を調べるのに使うtypeofとはまた別物)
keyof 型
でその型が持つプロパティから文字列リテラルのユニオン型(String Literal Union) を取得
const obj = { a: 1, b: 2, c: 3 } type tObj = typeof obj //type tObj = { a: number; b: number; c: number;} type tObjKey = keyof tObj // type tObjKey = "a" | "b" | "c" ;['a', 'b', 'c'].forEach((v) => { // console.log(obj[v]) // エラー /* 型 'string' の式を使用して型 '{ a: number; b: number; c: number; }' に インデックスを付けることはできないため、要素は暗黙的に 'any' 型になります。 型 'string' のパラメーターを持つインデックス シグネチャが 型 '{ a: number; b: number; c: number; }' に見つかりませんでした。 */ console.log(obj[v as "b"]) // 入りうる値に合致するリテラル型を指定するとエラーが出ないが console.log(obj[v as tObjKey]) // 正しくはこう })
参考