CHAPTER 3 · 5 LESSONS · 65 問

値のとりうる形をしぼる

「文字列または数値」のように複数の型を許し、使う前に確かめてから絞りこもう。

ここまでの型は、どれも「これ1つ」だった。string なら文字列だけ、number なら数値だけ。でも現実には、どちらもありうる場所がある。

たとえば入力された値。まだ選ばれていないなら undefined、選ばれたら文字列。あるいは、検索して見つかったら商品、見つからなければ null。こういう「AかB」を書けるのがユニオン型だよ。書き方は string | number のように | でつなぐだけだ。

ユニオン型を書くと、TypeScript の態度が変わる。両方の可能性があるあいだは、片方にしかできないことをさせてくれないstring | number の値に toUpperCase() を呼ぼうとすると止められる。数値だったときに壊れるからだ。これは意地悪ではなく、実際に起きるバグを先に見せてくれているんだよ。

だから次に必要になるのが絞り込みだ。if (typeof x === "string") と書くと、その中では TypeScript が「ここは文字列だ」と分かってくれる。人間がふつうに書く条件分岐が、そのまま型の情報として読み取られるんだ。確かめてから使うという当たり前の手順を、型が要求してくるようになる、と思ってほしい。

ユニオンにはもうひとつ大事な使い方がある。リテラル型だ。string ではなく "あか" | "あお" | "きいろ" のように、とりうる値そのものを型として並べる。こう書いておくと、打ちまちがえた文字列がその場ではじかれる。決まった選択肢を扱うときの定番だよ。

そして最後に anyunknown の話をする。any は「どんな型でもよい」という宣言で、書くと TypeScript はそこだけ何も見てくれなくなる。エラーは消えるけれど、消えたのはエラーであって問題ではない。困ったときの逃げ道として覚えるのではなく、なぜ避けるのかを知っておくために扱う。

代わりに使えるのが unknown だ。「まだ何か分からない」という意味で、使う前に必ず確かめさせてくれる。any との違いは一言でいうと、any は確かめなくても通してしまう、unknown は確かめないと通さない。この違いが分かると、型を書く目的そのものがはっきり見えてくるよ。

章の最後は、オブジェクトのユニオンを扱う。string | numbertypeof で見分けられたけれど、オブジェクトどうしのユニオンはそうはいかない。typeof はどちらも "object" としか答えてくれないからだ。そこで、それぞれの型に見分けるための目印を1つずつ持たせておく。目印さえあれば if で絞りこめて、その中では片方の型として安全に扱える。現場のデータはこの形をしていることがとても多いよ。

この章を終えると、「この値は3通りありうる」ということを型で表せて、しかも取りこぼしを機械に見張らせられるようになる。ここが、型のある言語のいちばん気持ちいいところだ。

この章のレッスン

どれか1つの型を書く

  1. 13どちらの型でもいいstring | number のように | でつないで、「どちらもありうる」を型に書こう。 問題へ
  2. 14決まった値だけを許す"あか" | "あお" のように値そのものを型にして、打ちまちがえをその場ではじこう。 問題へ

使う前にたしかめる

  1. 15使う前にたしかめるif (typeof x === "string") で絞りこんで、その中では片方の型として使おう。 問題へ
  2. 16any を避けて unknown を使うany は検査を止めてしまう。中身が分からない値は unknown で受けて、確かめてから使おう。 問題へ

オブジェクトを見分ける

  1. 17目印で見分けるユニオン共通の目印になるプロパティを持たせて、オブジェクトどうしのユニオンを if で見分けよう。 問題へ

つぎは「関数を型で守る」。アロー関数・省略できる引数・関数を渡す書き方に型をつけて、つなぎ目の事故をなくそう。