TypeScriptでユニオン型をオブジェクトのキーにしたい時はMapped Typesが良さそう(12/27 今日の知見)

今日の知見

TSでEnumを使いたくない時に、それっぽくUnion型を使うことがある。

type Fruits = "りんご"|"みかん"|"バナナ";

そんな時に、こういう制約↓をつけたオブジェクトを定義したいとする。

これならOKだが…

type FruitsPrice = {
  [key in Fruits]: Number 
} // OK

こっちはコンパイルエラーになる。

interface FruitsPrice {
  [key in Fruits]: Number;
} // NG
  • できればinterfaceで書きたいわけだが…今回はそうもいかない!という話

[key in Fruits]の書き方はMapped Typesと呼ばれるもので、現在interfaceには対応できない。( https://typescriptbook.jp/reference/type-reuse/mapped-types)

Mapped Typesは追加のプロパティが書けないなど、安心ではあるけど融通は効かない。Mapped Typesで必ずしも要望が叶うとは限らなそうだ

まとめ

  • 自作のユニオン型をオブジェクトのキーに指定したいときは、Mapped Typesを使うのが望ましい
    • しかし、制約はある
      • interfaceでは使えない
      • 例えば型にないキーを追加したいときは困る
        • …これ本当にどうしたらいいんだろう?解決策あるのかな?
    • だが、情熱はあるみたいに言うな