本稿では、配列型からその要素のunion型を導き出す方法を説明する。
やりたいこと
例えば、次のList
型のように、string
・number
・boolean
の要素を持ちうるArray
型があるとき、
type List = (string | number | boolean)[]
次のように、配列要素のユニオン型を求めたい。
type Elem = string | number | boolean
やりかた
indexed access operator(T[K]
のようなカギカッコ)使うと、配列要素の型を取り出すことができる:
type List = (string | number | boolean)[]
type Elem = List[number] // string | number | boolean になる
コンパイルが通ることを確認するコード:
const el1: Elem = '' // string
const el2: Elem = 0 // number
const el3: Elem = false // boolean
→このコードをTypeScript Playgroundで試す
どうしてList[number]
で配列要素のユニオン型が分かるの?
話を単純にするために、要素の型が1つだけの(=ユニオン型ではない)配列型を考えてみよう。次のスニペットのBooleans
型はboolean
な値からなる配列型である。
type Booleans = boolean[]
このBooleans
型について、いくつか自問自答してみよう。
-
Booleans
型の要素0番目の型は何になるか? 要素0番目に代入できる値はture
もしくはfalse
なので、答えは「boolean
型」である。 -
Booleans
型の要素1番目の型は何になるか? これも同様に、答えはboolean
型だ。 -
Booleans
型の要素2番目の型は? これも当然、boolean
型だ。
私達がこの自問自答で要素の型を考えられるように、TypeScriptでも要素の型を調べることができる。それが、indexed access operatorだ。
type Booleans = boolean[]
type TypeOfElement0 = Booleans[0] // 質問「要素0番目の型は何?」をコードで表現したもの
type TypeOfElement1 = Booleans[1] // 質問「要素1番目の型は何?」をコードで表現したもの
type TypeOfElement2 = Booleans[2] // 質問「要素2番目の型は何?」をコードで表現したもの
質問「要素0番目の型は何?」は、実はもっと一般化することができる。それが「要素N番目の型は何?」という質問だ。「N番目」の「N」に対応する、TypeScriptの表現はnumber
になる。
type Booleans = boolean[]
type TypeOfElement = Booleans[number] // 質問「要素N番目の型は何?」をコードで表現したもの
ここまでは、要素の型が1種類の配列型であるboolean[]
でindexed access operatorを説明してきたが、要素がユニオン型になっている配列にも話を広げてみよう。最初に示した、List
型で、先程の自問自答を考えてみることにする。
type List = (string | number | boolean)[]
-
List
型の要素0番目の型は何になるか? 要素0番目の値は、string
かもしれないし、number
かもしれないし、boolean
かもしれない。だから、答えは「string | number | boolean
型」である。 -
List
型の要素1番目の型は何になるか? これも同様に、答えはstring | number | boolean
型だ。 -
List
型の要素2番目の型は? これも当然、string | number | boolean
型だ。
つまり、質問を一般化すると、
-
List
型の要素N番目の型は? →string | number | boolean
型。
になる。これを先程のBooleans
の例と同様手順でTypeScriptのコードに起こすと、本稿冒頭の「やりかた」で示したスニペットになるわけだ:
type List = (string | number | boolean)[]
type Elem = List[number] // Elem は string | number | boolean になる