インデックスシグネチャとMappedTypesについて

に公開

今回はTypeScriptのインデックスシグネチャとMappedTypesについての投稿になります。

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

「どんなプロパティ名(※ 指定された任意の型を持つ)が来てもOK」にできる特殊な記法になります。
具体的に見ていきましょう。

/*
   プロパティ名はstirngで形成されていて
   それに対応する型はnumber
   のtype(文) Price
*/

type Price {
  [key: string]: number;
};

const data: Price = {
  // それぞれstring: numberの形になってる
  coffee: 350,
  tea: 300
}; 


ここに新たなプロパティを追加したい場合、下のようになります。

// waterがstring、200がnumberになってるので追加可能。
data.water = 200;

// これはエラーになる
data.juice = "無料";

このようにプロパティを後から追加できるので汎用性があります。


・Mapped Typesとは?

インデックスシグネチャとは違い、決められたプロパティ名(ユニオン型がよく使われます)に対して任意の型を指定していく記法になります。
決められたプロパティ名のみ使用できるのでインデックスシグネチャのように追加はできません。(※ ただし、インターセクションを使用すれば追加はできます。)

具体的に見ていきましょう。

type Drink = "beer" | "coffee" | "tea";

/*
   Mapped Typesを使用してDrinkPrice作成
   Pには Drinkから"beer""coffee""tea"が順番に入っていく
   型はnumberに指定
*/

type DrinkPrice = {
  [ P in Drink ]: number;
};

const drinkPrice: DrinkPrice = {
  beer: 350,
  coffee: 300,
  tea: 300
};


また既存の型を使用する方法もあります。

type Product = {
  name: string;
  price: number;
};

type Optional<T> = {
  /*
      keyofでオブジェクトのプロパティ名を文字列リテラル型のunionにする
      下の場合(Productを型引数にした場合)、 "name" | "string" になる
      プロパティのバリューには"型[キー名]"で型を与える
      今回はProductを利用してオプショナルな型を作成
  */
  [P in keyof T] ?: T[p];
};

type OptioanProduct = Optional<product>;
/*
   type OptionalProduct = {
      name?: string | undefined;
      age?: number | undefined; 
   }; 
   となる
*/