参考にさせていただいたページ
- keyof typeofの使い方 [TypeScript] - Qiita
- TypeScriptの型入門 - Qiita
- Index signature(インデックス型) - TypeScript Deep Dive 日本語版
はじめに
注意して使用しましょう。
「キーが未確定なobjectを先に作って後からデータを追加する」という処理が本当に必要なのかよく考える必要があると思います。
できるだけ先にキーを決めて、データの追加はその型に沿って追加するのが良いと思います。
良くない例
以下のコードでは「キーが未確定なobjectにデータを追加する方法」を使用していますが、良くない例です。
参考にさせていただいた「TypeScriptの型入門 - Qiita」のインデックスシグネチャの項にあるように、以下の例ではMyObj型の定義が曖昧になってしまい、TypeScriptの良さが活かせていません。
// MyObj型を定義 type MyObj = { [key: string]: number // ここでnumberだけにしているのが良くない } // 変数myObjをMyObj型で定義 const myObj: MyObj = {} // データを追加できる myObj['keyNameA'] = 0 myObj['keyNameB'] = 1 // 変数keyに'example'を代入 const key: string = 'example' // myObj.exampleは存在しないキーなので、変数myVariableにはundefinedが入る const myVariable = myObj[key] // 実際にはmyVariableはundefinedだが、この後の処理でnumberとして型推論がされるので不具合の元になってしまう console.log(myVariable) // undefined
少し改善する
以下のように改善できます。
// MyObj型を定義 type MyObj = { [key: string]: number | undefined // ここでnumber | undefinedにしておくと、myVariableが後の処理で正しく型推論される }
「キーが未確定なobjectを先に作って後からデータを追加する」という処理が本当に必要なのか考える
以下のようにできるのであれば、より安全です。
// MyObj型を定義 type MyObj = { keyNameA: number keyNameB: number } // 変数myObjをMyObj型で定義 const myObj: MyObj = { keyNameA: 0, keyNameB: 1, } // 変数keyに'example'を代入 const key: string = 'example' // MyObj型が予め厳格に定義できているため、ここでコンパイルエラーになり、不具合が未然に防げる const myVariable = myObj[key] // この後の処理も安心 console.log(myVariable)
結局のところ
上記した「良くない例」のように [key: string]
を使用したり、[index: number]
を使用することで、objectのキーやarrayのインデックスを抽象的にすることができますが、使用方法を誤ると型推論が正しく行われなくなってしまいます。
「キーが未確定なobjectを先に作って後からデータを追加する」という処理が本当に必要なのか、それが有効な方法なのかをよく考える必要があると思います。
型推論が正しく行われるように書きましょう。