配列から全要素の型を生成する
前ページでは、配列から全要素の型を生成する方法が登場しました。
tsconstcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = (typeofcurrencies )[number];
tsconstcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = (typeofcurrencies )[number];
typeof currencies[number]という書き方は、初めて見ると理解に苦しむコードかもしれません。そのためより詳しく説明します。
前ページのコードを観察する
配列からある要素の型を生成するコードについて、前ページに続き通貨の配列でもう一度確認します。
tsconstcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = (typeofcurrencies )[2];
tsconstcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = (typeofcurrencies )[2];
ここで、typeof currencies[2]の2は、前ページでリテラル型と説明していますが本当でしょうか?次のコードで確認してみます。
tsconstcurrencies = ["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
tsconstcurrencies = ["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が値として解釈されるコードではエラーになってしまいました。
では明確にリテラル型だとわかるコードも試してみましょう。
tsconstcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeIndex = 2;typeCurrency = (typeofcurrencies )[Index ];
tsconstcurrencies = ["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型の代わりにリテラルのユニオン型を使ってみましょう。
tsconstcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = (typeofcurrencies )[0 | 1 | 2 | 3 | 4 | 5];
tsconstcurrencies = ["CNY", "EUR", "GBP", "JPY", "KRW", "USD"] asconst ;typeCurrency = (typeofcurrencies )[0 | 1 | 2 | 3 | 4 | 5];
0 | 1 | 2 | 3 | 4 | 5型でもcurrencies配列から全要素の型を生成することができました。このようにnumber型は数値のリテラル型のワイルドカードとして振る舞うことがわかります。
一般化する
このページの締めくくりに一般化したコードを示します。
tstypeList = (string | number | boolean)[];typeElem =List [number];
tstypeList = (string | number | boolean)[];typeElem =List [number];
List型からList[number]という書き方ですべての要素の型であるstring | number | booleanが生成できました。
アンチパターンの紹介
次のように具体的なインデックスで同じ型を生成することは可能ですが、アンチパターンなので注意してください。
tstypeList = (string | number | boolean)[];typeElem =List [0]; // 避けるべき書き方
tstypeList = (string | number | boolean)[];typeElem =List [0]; // 避けるべき書き方
この書き方がアンチパターンである理由はList型をタプル型だと混乱させてしまう可能性があるためです。List[0]は特定の要素から型を生成しているため、各要素の型が同じ型ではない、つまりListが配列型ではなくタプル型だからこの書き方をしていると誤解させる可能性があります。配列型はどの要素の型も同じものとして扱うので、List[number]の書き方が適切です。