Typescript(インデックスシグネチャ)
はじめに
今回の記事はインデックスシグネチャ(インデックス型)についてです。前回記事のインターフェースなども利用した記事になっていますのでインターフェースについてよくわからないと感じる方は前回記事
Typescript(インターフェース) - 駆け足エンジニアの記録
参照で宜しくお願いします。
インデックスシグネチャの定義
[key:T]:U・・・これをオブジェクトリテラルで挟むことで、このオブジェクトについては型Tの全てのキー(プロパティ名)は、型Uの値を持たなければならない。
実際の使用例で確認しましょう。
interface MovietheatreSeatingAssigment { [seatNUmber: string]: string; } const users : MovietheatreSeatingAssigment = { k12: "Max", k13: "Green", k14: "Jon", };
このケースは映画館の座席の割当についてのオブジェクトです。インターフェースなどで、オブジェクトから1つ1つキーと値の型を定義するのはあまりに面倒です。インデックスシグネチャを使うことで、オブジェクトがより多くのキーを含む可能性があることをTypescriptに伝える事ができます。
インデックスシグネチャの注意点,ユースケース
①キーの型はstring型かnumber型
先程はキーの型がstringでしたがnumber型も可能です。
interface Ranking { [rank: number]: string; } const ranking: Ranking = { 1: "Mikasa Ackermann", 2: "Reiner Brown", 3: "Bertolt Hoover", };
余談ですが、オブジェクトのキーは文字列という制約があります。今回のケースではキーはnumber型となっていますが、オブジェクトのキーをnumber型で設定したとしても文字列で自動変換されます。以下はjavascriptのコードです。
const obj = { 0: 'zero', 1: 'one, }; console.log(Object.keys(obj));//(2) ["0", "1"]
②キーの型が同じシグネチャを重複することはできない。
プロパティ名が異なる場合でも、その型が等しければエラーが起きます。
interface Ranking { [rank: number]: string; [rankgai:number]:string//エラー(number インデックス シグネチャが重複しています。) }
キーの型を変えればエラーが出ませんでした。
interface Ranking { [rank: number]: string; [rankgai: string]: string; } const ranking: Ranking = { 1: "Mikasa Ackermann", 2: "Reiner Brown", 3: "Bertolt Hoover", "104期生": "Armin Harlert", };
③value(値)の型は揃える
インデックスシグネチャが重複する場合、キーの型は異なる必要があったのに対し、valueの型は揃える必要があります。(直前のコード参照)
またインデックスシグネチャを利用するケースは以下のようなことも可能です。ここでもvalueの型は揃える必要があります。
interface obj { belongs: string; [key: string]: string; } //valueの型はstring const person1: obj = { belongs: "tyousaheidan", name: "Eren Jaeger", birthdata: "3/30", };
④readonlyとの共存
インデックスのシグネチャをreadonlyとしてマークすることもできます。
interface Ranking { readonly [rank: number]: string; } const ranking: Ranking = { 1: "Mikasa Ackermann", 2: "Reiner Brown", 3: "Bertolt Hoover", }; ranking[0] = "Eren Jaeger"; //エラー(型 'Ranking' のインデックス シグネチャは、読み取りのみを許可します。)
余談
オブジェクトのプロパティを動的に生成するcomputed property namesを使うと型推論はインデックス型となります。以下のコードをコピーし、vscodeなどのエディタ上で型推論を見てみてください。
let i = 0; const hokage = { [`${++i}代目火影`]: "千手柱間", [`${++i}代目火影`]: "千手扉間", [`${++i}代目火影`]: "猿飛ヒルゼン", [`${++i}代目火影`]: "波風ミナト", }; console.log(hokage);//1代目火影: "千手柱間" //2代目火影: "千手扉間" //3代目火影: "猿飛ヒルゼン" //4代目火影: "波風ミナト"