今日の知見
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
で必ずしも要望が叶うとは限らなそうだ
- ここで疑問: インデックスシグネチャ(
[key: Fruits] : Number
)は書けないのか?これならinterfaceでも書けるはずだ- https://typescriptbook.jp/reference/values-types-variables/object/index-signature
-
インデックス型のフィールド名の型はstring、number、symbolのみが指定できます。
Fruits
はユニオン型だから、インデックス型ではフィールド名に指定できない!
まとめ
- 自作のユニオン型をオブジェクトのキーに指定したいときは、
Mapped Types
を使うのが望ましい- しかし、制約はある
interface
では使えない- 例えば型にないキーを追加したいときは困る
- …これ本当にどうしたらいいんだろう?解決策あるのかな?
- だが、情熱はあるみたいに言うな
- しかし、制約はある