CHAPTER 3 · 5 LESSONS · 65 問
値のとりうる形をしぼる
「文字列または数値」のように複数の型を許し、使う前に確かめてから絞りこもう。
ここまでの型は、どれも「これ1つ」だった。string なら文字列だけ、number なら数値だけ。でも現実には、どちらもありうる場所がある。
たとえば入力された値。まだ選ばれていないなら undefined、選ばれたら文字列。あるいは、検索して見つかったら商品、見つからなければ null。こういう「AかB」を書けるのがユニオン型だよ。書き方は string | number のように | でつなぐだけだ。
ユニオン型を書くと、TypeScript の態度が変わる。両方の可能性があるあいだは、片方にしかできないことをさせてくれない。string | number の値に toUpperCase() を呼ぼうとすると止められる。数値だったときに壊れるからだ。これは意地悪ではなく、実際に起きるバグを先に見せてくれているんだよ。
だから次に必要になるのが絞り込みだ。if (typeof x === "string") と書くと、その中では TypeScript が「ここは文字列だ」と分かってくれる。人間がふつうに書く条件分岐が、そのまま型の情報として読み取られるんだ。確かめてから使うという当たり前の手順を、型が要求してくるようになる、と思ってほしい。
ユニオンにはもうひとつ大事な使い方がある。リテラル型だ。string ではなく "あか" | "あお" | "きいろ" のように、とりうる値そのものを型として並べる。こう書いておくと、打ちまちがえた文字列がその場ではじかれる。決まった選択肢を扱うときの定番だよ。
そして最後に any と unknown の話をする。any は「どんな型でもよい」という宣言で、書くと TypeScript はそこだけ何も見てくれなくなる。エラーは消えるけれど、消えたのはエラーであって問題ではない。困ったときの逃げ道として覚えるのではなく、なぜ避けるのかを知っておくために扱う。
代わりに使えるのが unknown だ。「まだ何か分からない」という意味で、使う前に必ず確かめさせてくれる。any との違いは一言でいうと、any は確かめなくても通してしまう、unknown は確かめないと通さない。この違いが分かると、型を書く目的そのものがはっきり見えてくるよ。
章の最後は、オブジェクトのユニオンを扱う。string | number は typeof で見分けられたけれど、オブジェクトどうしのユニオンはそうはいかない。typeof はどちらも "object" としか答えてくれないからだ。そこで、それぞれの型に見分けるための目印を1つずつ持たせておく。目印さえあれば if で絞りこめて、その中では片方の型として安全に扱える。現場のデータはこの形をしていることがとても多いよ。
この章を終えると、「この値は3通りありうる」ということを型で表せて、しかも取りこぼしを機械に見張らせられるようになる。ここが、型のある言語のいちばん気持ちいいところだ。
この章のレッスン
どれか1つの型を書く
使う前にたしかめる
オブジェクトを見分ける