配列から型を生成する
単位のように振る舞うことを期待されて定義されたコレクションは少なくないでしょう。今回はコレクションでも主に配列に焦点を当てそれらから型を生成する方法の紹介です。
通貨の配列から通貨の型を作りたい
国際的な外貨を使うことができるサービスを開発していたとします。サポートしている通貨を配列で保持しているとし次のようになっているとします。
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"];
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"];
このようなとき、このJavaScriptの資産をできるだけ変更せずに貨幣の型 (ユニオン型) を作ることができれば今後便利そうです。つまり次のようなユニオン型です。
ts
typeCurrency = "CNY" | "EUR" | "GBP" | "JPY" | "KRW" | "USD";
ts
typeCurrency = "CNY" | "EUR" | "GBP" | "JPY" | "KRW" | "USD";
typeof
これはJavaScriptのtypeof
ではなくTypeScriptのtypeof
です。typeof
はTypeScriptがその変数をどのような型であるかと認識しているかかを教えてくれます。
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"];typeCurrency = typeofcurrencies ;
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"];typeCurrency = typeofcurrencies ;
予想されている方が多かったかもしれませんがstring[]
型と出てしまいました。ではこれをどうすればstring
ではなく定数値で取得できるでしょうか。それは定数値で取得したいオブジェクトにas const
をつけると取得できます。
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = typeofcurrencies ;
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = typeofcurrencies ;
定数 (リテラル型) は取れましたが依然配列のままです。これをユニオン型で取るためには考え方を逆転させる必要があります。
何番目のリテラル型が欲しいか
たとえば'GBP'
が欲しいとします。'GBP'
は2番目なのでcurrencies
の2番目の型を取れば希望のリテラル型が取れます。
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = typeofcurrencies [2];
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = typeofcurrencies [2];
'GBP'
を取ることができました。
すべてのリテラル型が欲しい
本題です。まさか次のようにするわけには行かないのでもっと賢い方法を考える必要があります。
ts
type Currency = typeof currencies[0] | typeof currencies[1] | typeof currencies[2] | ....
ts
type Currency = typeof currencies[0] | typeof currencies[1] | typeof currencies[2] | ....
そこで思いつくのはtypeof
をしているときのインデックスです。実はこれもリテラル型でありcurrencies
の2
のリテラル型を取ることを意味しています。
配列はnumber型のインデックスに要素を代入しているオブジェクトなのでこのリテラル型のインデックスの代わりにnumber
を使うことによって
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = typeofcurrencies [number];
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = typeofcurrencies [number];
と希望のユニオン型を取得できます。