配列から全要素の型を生成する
前ページでは、配列から全要素の型を生成する方法が登場しました。
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = (typeofcurrencies )[number];
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = (typeofcurrencies )[number];
typeof currencies[number]
という書き方は、初めて見ると理解に苦しむコードかもしれません。そのためより詳しく説明します。
前ページのコードを観察する
配列からある要素の型を生成するコードについて、前ページに続き通貨の配列でもう一度確認します。
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = (typeofcurrencies )[2];
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = (typeofcurrencies )[2];
ここで、typeof currencies[2]
の2
は、前ページでリテラル型と説明していますが本当でしょうか?次のコードで確認してみます。
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;constindex = 2 asconst ;type'index' refers to a value, but is being used as a type here. Did you mean 'typeof index'?2749'index' refers to a value, but is being used as a type here. Did you mean 'typeof index'?Currency = (typeofcurrencies )[]; index
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;constindex = 2 asconst ;type'index' refers to a value, but is being used as a type here. Did you mean 'typeof index'?2749'index' refers to a value, but is being used as a type here. Did you mean 'typeof index'?Currency = (typeofcurrencies )[]; index
2
が値として解釈されるコードではエラーになってしまいました。
では明確にリテラル型だとわかるコードも試してみましょう。
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeIndex = 2;typeCurrency = (typeofcurrencies )[Index ];
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeIndex = 2;typeCurrency = (typeofcurrencies )[Index ];
これでtypeof currencies[2]
の2
はリテラル型であることがはっきりしました。
数値のリテラル型とnumber
型
2
のリテラル型とnumber
型の関係を集合で表現すると、2
⊂number
と書くことができます。他の表現をすると、0
、1
、2
..など数値のリテラル型のいずれかの型として振る舞うのがnumber
型です。
「いずれかの型」といえばユニオン型の出番です。
📄️ ユニオン型
TypeScriptのユニオン型(union type)は「いずれかの型」を表現するものです。
number
型の代わりにリテラルのユニオン型を使ってみましょう。
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = (typeofcurrencies )[0 | 1 | 2 | 3 | 4 | 5];
ts
constcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = (typeofcurrencies )[0 | 1 | 2 | 3 | 4 | 5];
0 | 1 | 2 | 3 | 4 | 5
型でもcurrencies
配列から全要素の型を生成することができました。このようにnumber
型は数値のリテラル型のワイルドカードとして振る舞うことがわかります。
一般化する
このページの締めくくりに一般化したコードを示します。
ts
typeList = (string | number | boolean)[];typeElem =List [number];
ts
typeList = (string | number | boolean)[];typeElem =List [number];
List
型からList[number]
という書き方ですべての要素の型であるstring | number | boolean
が生成できました。
アンチパターンの紹介
次のように具体的なインデックスで同じ型を生成することは可能ですが、アンチパターンなので注意してください。
ts
typeList = (string | number | boolean)[];typeElem =List [0]; // 避けるべき書き方
ts
typeList = (string | number | boolean)[];typeElem =List [0]; // 避けるべき書き方
この書き方がアンチパターンである理由はList
型をタプル型だと混乱させてしまう可能性があるためです。List[0]
は特定の要素から型を生成しているため、各要素の型が同じ型ではない、つまりList
が配列型ではなくタプル型だからこの書き方をしていると誤解させる可能性があります。配列型はどの要素の型も同じものとして扱うので、List[number]
の書き方が適切です。