🕌

インデックスシグネチャ

2020/10/05に公開1

インデックスシグネチャとは

今回の記事はオブジェクト型の型アノテーションの一つであるインデックスシグネチャについてまとめます。
インデックスシグネチャの定義は
{[key:T]:U}・・・このオブジェクトについては型Tの全てのキー(プロパティ名)は、型Uの値を持たなければならないことを意味します。

type MovietheatreSeatingAssigment = {
  [seatNUmber: string]: string;
};
const users: MovietheatreSeatingAssigment = {
  k12: "Max",
  k13: "Green",
  k14: "Jon",
};

このケースは映画館の座席の割当についてのオブジェクトです。型エイリアスによるオブジェクト型の型注釈によって、オブジェクトから1つ1つキーと値の型を定義するのはあまりに面倒です。

インデックスシグネチャを使うことで、オブジェクトがより多くのキーを含む可能性があることをTypescriptに伝える事ができます。


インデックスシグネチャの注意点

①キーの型はstring型かnumber型

先程はキーの型がstringでしたがnumber型も可能です。

type Ranking = {
  [rank: number]: string;
};
const ranking: Ranking = {
  1: "Mikasa Ackermann",
  2: "Reiner Brown",
  3: "Bertolt Hoover",
};

②キーの型が同じシグネチャを重複することはできない

プロパティ名が異なる場合でも、その型が同じであればエラーが起きます。

interface Ranking {
  [rank: number]: string;
  [notRanked:number]:string//エラー(number インデックス シグネチャが重複しています。)
}

キーの型を変えればエラーは生じません。

type Ranking = {
  [rank: number]: string;
  [notRanked: string]: string;
};
const ranking: Ranking = {
  1: "Mikasa Ackermann",
  2: "Reiner Brown",
  3: "Bertolt Hoover",
  "104期生": "Armin Harlert",
};

③value(値)の型は揃える

インデックスシグネチャが重複する場合、キーの型は異なる必要があったのに対し、valueの型は揃える必要がありました。(直前のコード参照)

またインデックスシグネチャを利用するケースは以下のようなことも可能です。ここでもvalueの型は揃える必要があります。

type Obj = {
  belongs: string;
  [key: string]: string;
} //valueの型はどちらもstring

const person1: Obj = {
  belongs: "Research Corps",
  name: "Eren Jaeger",
  birthdata: "3/30",
};

その他の気づき

直前の例ですが、以下のようなオブジェクトの定義でもエラーは生じません。

type Obj = {
  belongs: string;
  [key: string]: string;
}; 

const person1: Obj = {
  belongs: "Research Corps",
};

インデックスシグネチャによる型注釈を完全に無視したコードです。ここから考察するに、インデックスシグネチャを定義する裏ではオプション?が付くというイメージでしょうか。

またオブジェクト型を宣言する時に使用できる修飾子であるreadonlyは,インデックスシグネチャにも利用可能です。

type Ranking = {
  readonly [rank: number]: string;
};
const ranking: Ranking = {
  1: "Mikasa Ackermann",
  2: "Reiner Brown",
  3: "Bertolt Hoover",
};
ranking[0] = "Eren Jaeger";
//エラー(型 'Ranking' のインデックス シグネチャは、読み取りのみを許可します。)

Discussion

nishinanishina

丁寧にまとめてくださりありがとうございます!

①キーの型はstring型かnumber型

補足ですが、TypeScript 4.4 変更点 まとめによるとTypeScript 4.4からsymbolやTemplate Literal Typesがインデックスシグネチャで利用できるようになったようです。

実行結果は以下の通りです。

// symbol型をインデクスシグネチャのキーに利用する例

type ObjType = {
    [key: symbol]: string
}
const sym = Symbol();

const obj: ObjType = {
    [sym]: "value"
};
console.log(obj[sym]); // "value"
// Template Literal Typesをインデクスシグネチャのキーに利用する例

type Events = { [key in `on${string}`]: boolean; }
// type Events = { [x: `on${string}`]: boolean; }   

const events: Events = {
    onClick: true,
    onMousedown: true,
    onMouseup: true,
    onMyCustomEvent: false,
}

参考: