「TypeScriptの型入門」で手を動かす - その6
本日は「TypeScriptの型入門」の「union型(合併型)」からです。
union型(合併型)
- ジェネリクスは型のある言語なら普通にある
- union型を持っている言語は多く無い
- TypeScriptはunion型のサポートに力を入れている
- union型は値が複数の型のどれかに当てはまるような型を表している
- 複数の型を
|
でつなぐstring | number
なら、stringまたはnumber- 確かに、javaもこういうふうにはかけないな、何か実現方法あるのかな
- 複数の型を
union型の絞り込み
type HogePiyo = Hoge | Piyo
で新しくunion型で定義した場合、そのままでは使いづらい- HogeかもしれないしPiyoかもしれないので、無い可能性があるプロパティは参照できない
Hoge | Piyo
のような型の値が与えられた場合、実行時に判定する必要がある- TypeScriptでは適切に型を絞り込んでくれる機能がある
- if分岐で
in
でプロパティがあるかを判定する
- if分岐で
- 余計なプロパティがあると、誤判定的な挙動をするので怖い
- 動かしてみるとHogePiyoにそもそも余計なプロパティを追加できなかったな
typeofを用いた絞込み
string === typeof value
のように絞り込みができる- あれ、これプリミティブ型以外だめだったりしないのかな..
- 関数の引数に対するバリデーションとか、ラインタイム依存の場合は駄目な気がする。
- あれ、これプリミティブ型以外だめだったりしないのかな..
nullチェック
- union型がよく使われるのは、nullableな値を扱いたい場合
- undefinedも
string | null
なら文字列の値があるかもしれないしnullかもしれないvalue != null
でチェックすると、型を絞り込んでくれる&&
や||
の短絡実行でも型検査してくれる
代数的データ型っぽいパターン
- プリミティブ型ならいい感じにunion型の絞り込みができるがオブジェクトはできない
- リテラル型とunion型を組み合わせることで代数的データ型(タグ付きunion)を再現するパターンが推奨
これ、なんか難しいんですよね。
- 値があるかもしれない無いかもしれないことを表すoption型をTSで表現
type Option<T> = Some<T> | None
- option型はsomeまたはnone、someだと値がある
- SomeとNoneは共通のtypeプロパティを持っている
- typeプロパティで someかnoneかを判定する
- TypeScriptプログラミングにおいて頻出
代数的データ型とは
- そもそも「代数」とは
- 特定の数の代わりとして用いられる文字・記号などのこと(wikipediaより)
- データ型を変数のように文字・記号で足したり引いたりできる型?
- 代数的データ型とは
- 「かつ」と「または」で表すことができる型
- 「または」の型はコンパイラによってもれなくチェックされる必要がる
うーむ。関数型言語で使われることが多い概念ぽいな。Haskellでの説明がちょこちょこ出てくる。
この記事では、以下と記載
以下の3つを合わせて代数的データ型と呼びます。 1. 列挙型 (他言語のenumに相当) 2. 直積型 (他言語のstructに相当) 3. 直和型 (他言語のunionに相当)
結局は、union型ならnumber | string
のように、numberかstringかどちらかの型である、というのを定義できて、オブジェクトの場合は、ランタイムで型の判定はできないから(型情報はランタイムでは残らない)、リテラル型でtypeプロパティとかを定義して、どの型なのかを擬似的に判定してるよ、ってことなのかな。
で、単純にtypeof
では判定できないので、擬似的に判定する作りが重くなっちゃてるが、TypeScriptの限界だよと、一旦この理解にしておこう。
union型オブジェクトのプロパティ
- オブジェクト同士のunion型を作った場合、プロパティアクセスの挙動は概ね期待通りの結果となる
HogePIyo
がHoge
とPiyo
を取るかたなら、それの共通プロパティfoo
だけにアクセス可能- また、
foo
プロパティの型は、Hoge
とPiyo
それぞれのfoo
プロパティの型のunion型になる
長かったー!
ちょこちょこ、なんかテンションだかモチベだか下がって、時間かかっちゃったけど、まぁまぁ理解できたかな。
長かったので、途中で分割しても良かったかも。(モチベ維持のために)
次は「never型」から手を動かします!