どうもフロントエンドエンジニアのまさぴょんです!
今回はTypeScriptのインデックス・シグネチャー(Index-Signature)について解説します。
インデックス・シグネチャー(Index-Signature)とは?
TypeScript初学者の強い味方『サバイバルTypeScript』によると次のように説明されています。
TypeScriptで、オブジェクトのフィールド名をあえて指定せず、プロパティのみを指定したい場合があります。
そのときに使えるのがこのインデックス型(index signature)です。
たとえば、プロパティがすべて
number
型であるオブジェクトは次のように型注釈します。let obj: {
[K: string]: number;
};
フィールド名の表現部分が
[K: string]
です。この
K
の部分は型変数です。任意の型変数名にできます。
K
やkey
にするのが一般的です。
string
の部分はフィールド名の型を表します。インデックス型のフィールド名の型は
引用元: 『サバイバルTypeScript』インデックス型 (index signature)string
、number
、symbol
のみが指定できます。
つまり、Index-Signatureとは、Object型の「key名を変数化」できる記法だと言うことです。
let obj { [ key名: string ]: number };
と記述すれば、このobj(Object型)の「key名は変数化」(型変数)されており、string型なら自由に設定することができるようになっています。
このようなkey名を変数化することで、汎用的に使い回すことができます。
Index-Signatureで使える型は、今のところ、string, number, symbol 型のいずれかなので、使用する際はその点に注意する必要があります。
サンプルコード
それでは、より実務に近いSample-Codeを掲載したので、「TypeScript Playground」などを使って実行してみてください。
// < 型定義 > の領域展開 ----------------------------------------------------------------------------------------
interface ItemInfo { // 1. ItemInfo: 商品の基本情報
id: number;
name: string;
price: number;
stock: number;
enableBuyFlag: boolean; // 購入可能Flag
stockLimitFlag: boolean; // 在庫が少なくなったら発注するようにSwitchされるFlag
}
// Index-Signature
interface CartItemObj { // 2. CartItemObj: カートに入る商品
[key: string]: ItemInfo; // key名は、string型なら何が入ってもOK!
}
interface CartInfo { // 3. CartInfo: カートの情報
userId: number;
userName: string;
cartItem: CartItemObj[];
address: string;
telephone: string;
}
// -------------------------------------------------------------------------------------------------------------
const cart: CartInfo = { // 1. カート
userId: 1,
userName: "ロボ玉",
cartItem: [],
address: "グンマー帝国",
telephone: "080-1234-5678"
};
// 2. 商品リスト
const itemList = ["apple", "greep", "mikan", "orange", "magoro", "momo", "robotama"] as const;
const apple: ItemInfo = { // 3. 商品詳細 Ver.apple
id: 1,
name: "apple",
price: 100,
stock: 12,
enableBuyFlag: true,
stockLimitFlag: false,
};
const greep: ItemInfo = { // 4. 商品詳細 Ver.greep
id: 2,
name: "greep",
price: 200,
stock: 7,
enableBuyFlag: true,
stockLimitFlag: false,
};
const addCart = (item: ItemInfo): void => { // 5. カートに追加する関数
for(const itemName of itemList){
if(itemName == item.name) {
console.log(item.name, ": 登録・商品");
const key = item.name;
cart.cartItem.push({ [key]: item }); // ブラケット記法でkey名に変数を埋め込む
}
};
};
addCart(apple);
addCart(greep);
console.log(cart);
// < 出力結果 >
// {
// "userId": 1,
// "userName": "ロボ玉",
// "cartItem": [
// {
// "apple": {
// "id": 1,
// "name": "apple",
// "price": 100,
// "stock": 12,
// "enableBuyFlag": true,
// "stockLimitFlag": false
// }
// },
// {
// "greep": {
// "id": 2,
// "name": "greep",
// "price": 200,
// "stock": 7,
// "enableBuyFlag": true,
// "stockLimitFlag": false
// }
// }
// ],
// "address": "グンマー帝国",
// "telephone": "080-1234-5678"
// }
簡単に説明すると、「2. CartItemObj: カートに入る商品」の型定義でIndex-Signatureを使用しており、「3. CartInfo: カートの情報」では「cartItem」というkey名にCartItemObjの配列を定義しています。
そして、実際の処理BlockではitemListの商品名をIndex-Signatureの型変数(key名)に使って、商品情報(ItemInfo)と紐づけています。
このように使っていくと実務でも役立つこと間違いなしなので、活用してみてください。
まとめ
- Index-Signatureは、key名を変数(型変数)として定義できる。