VIDEO LESSON
TypeScriptのユニオン型と型ガード:型の絞り込みからneverによる網羅チェックまでの解説動画
再生時間 8:01動画を別のタブで開く ↗
動画の字幕・文字起こしを読む
再生中の字幕を濃い黒で表示し、一番上に追従します。字幕の行を選ぶと、その位置から再生できます。
- 0:00こんにちは。
- 0:00タイプスクリプト入門、第六回はユニオン型と型ガードです。
- 0:05前回は関数の型を学びました。
- 0:07今回は、一つの値が複数の型を取り得る場合に、型を安全に扱う方法を学びます。
- 0:14キーワードは三つです。
- 0:15候補を列挙するユニオン型、候補を減らす絞り込み、そして絞り込みの仕組みである型ガードです。
- 0:23さらに、外部から届いた不明な値を検証する方法と、処理漏れをコンパイル時に見つけるネバーの使い方まで、
- 0:28配送状態を題材に順に確認します。
- 0:34この回を終えるころには、状態ごとに必要なデータが違うデータを、型で安全に表せるようになります。
- 0:41型は実行時には残りませんが、書いている最中とコンパイルの段階で、間違いを早く見つける助けになります。
- 0:50まずユニオン型です。
- 0:51ユニオン型は、値が取り得る型を縦棒でつないで列挙したものです。
- 0:56たとえば文字列か数値、という変数は、文字列と数値のどちらも代入できますが、
- 1:01それ以外の真偽値などを入れようとすると型エラーになります。
- 1:06大切なのは、ユニオン型の値には、すべての候補に共通する操作しか、そのままでは使えないことです。
- 1:14文字列専用のメソッドを呼ぼうとするとエラーになります。
- 1:18何でも許すエニー型に変えてしまえばエラーは消えますが、存在しないメソッドを呼ぶ誤りも見つけられなくなります。
- 1:27候補を絞ってから使う、というのが基本の流れです。
- 1:30候補を絞る代表的な方法が、タイプオブによる判定です。
- 1:35参照番号を整形する関数で見てみましょう。
- 1:38この関数は、文字列か数値を受け取り、文字列を返します。
- 1:42タイプオブで数値かどうかを判定し、数値なら数値専用のメソッドで丸めて表示します。
- 1:49そうでなければ、文字列として空白を取り除き、大文字に変換します。
- 1:54呼び出し結果は、数値の四十二がナンバー四十二、空白付きの文字列が大文字に整えられて表示されます。
- 2:02判定の中でだけ、その型専用の操作が安全に使える点に注目してください。
- 2:08なお、数値であることは、業務上正しい番号であることとは別です。
- 2:13必要なら整数かどうかなどを別途検証しましょう。
- 2:16このように、判定や処理の流れから型の候補を減らすことを、型の絞り込みと呼びます。
- 2:22ポイントは、早期にリターンする書き方です。
- 2:25数値の分岐でリターンした後は、その先のコードでは数値の可能性が消え、残る候補は文字列だけになります。
- 2:32コンパイラはこの流れを追って、候補を自動で減らしてくれます。
- 2:36そして、タイプオブのように型を判定する仕組みそのものを、型ガードと呼びます。
- 2:41等しいかどうかの比較や、値があるかどうかの確認も、絞り込みとして働きます。
- 2:46絞り込みは特別な記法ではなく、普段の条件分岐の中で起きていることなのです。
- 2:51次に、状態とデータを組み合わせる方法です。
- 2:55配送の状態を、単なる文字列と、任意の宛先やエラー文で表すと、配送成功なのに宛先がない、
- 3:01という矛盾したデータも作れてしまいます。
- 3:06そこで、状態ごとにオブジェクトの形を分けます。
- 3:10配送待ちには追加のデータはなし、送信済みには宛先が必須、失敗には理由が必須、
- 3:18という三つの形を用意し、共通のステータスには、それぞれ異なる文字列リテラルを指定します。
- 3:25このように、判別に使う共通プロパティを持つユニオン型を、判別可能なユニオンと呼びます。
- 3:33状態と必要なデータを、型のレベルで結び付けられるのが利点です。
- 3:38この形なら、コンパイラが状態とデータの正しい組み合わせを覚えてくれます。
- 3:45判別可能なユニオンは、スイッチ文と相性がよい書き方です。
- 3:49ステータスで分岐すると、各分岐の中では、その状態のオブジェクトだけが候補に残ります。
- 3:56送信済みの分岐では宛先を、失敗の分岐では理由を、そのまま安全に読み取れます。
- 4:02逆に、別の状態のプロパティを無条件に読もうとすると型エラーになります。
- 4:08状態とデータの取り違えを、コンパイル時に見つけられるわけです。
- 4:13表示の文言は状態ごとに決まります。
- 4:16配送待ち、宛先付きの配送完了、理由付きの配送失敗です。
- 4:20分岐を書く側も読む側も、今どの状態を扱っているかが明確になります。
- 4:25すべての状態を処理した後のデフォルト分岐には、残る候補がありません。
- 4:31その、値が存在しないことを表す型がネバーです。
- 4:34この性質を網羅チェックに使います。
- 4:36デフォルトでは、ネバー型の引数だけを受け取る関数を呼びます。
- 4:41もし新しい状態、たとえば再試行中を追加したのに分岐を足し忘れると、デフォルトにその状態が残ってしまい、
- 4:47ネバーを期待する場所に渡せなくなって型エラーになります。
- 4:53つまり、処理漏れを実行前にコンパイルエラーとして教えてくれる仕組みです。
- 4:58状態を増やすときの安全網として、ぜひ覚えておきましょう。
- 5:02外部から届いた値は、型が不明なアンノウンとして受け取るのが安全です。
- 5:08そのままでは使えないため、検証してから型を付けます。
- 5:12ここで使うのが、独自の型ガードです。
- 5:16戻り値の型に型述語を書くと、真を返したときに、その値が宣言した型であるものとして絞り込めます。
- 5:24配送状態の検証では、まずオブジェクトであることとヌルでないことを確かめ、
- 5:30ステータスがあるかを確認し、状態ごとに必要な項目が文字列で存在するかまで調べます。
- 5:37ただし型述語は、実装が正しいという前提で動きます。
- 5:41検証の書き間違いはコンパイラには証明できないため、不足した項目やヌルなどのテストも必要です。
- 5:49では、実際に動かして確かめましょう。
- 5:52不明な値の配列に、正しい三つの状態と、宛先が欠けたデータと、ヌルを用意します。
- 5:59一つずつ検証し、配送状態として認められたものだけを表示関数に渡します。
- 6:05結果は、配送待ち、宛先付きの配送完了、理由付きの配送失敗の順に表示され、
- 6:11宛先が欠けたデータとヌルは、不正な配送状態として拒否されます。
- 6:17ここで、型を断定するアズだけでは、この検証は実行されません。
- 6:22断定はコンパイラへの言い切りであり、実行時のチェックにはならないからです。
- 6:28検証を通った値だけが、安全な表示処理へ進めます。
- 6:33コンパイルはストリクトを有効にして行い、生成されたジャバスクリプトをノードで実行して確認しました。
- 6:41よくある落とし穴も押さえておきましょう。
- 6:44第一に、値そのもので判定すると、空文字やゼロも一緒に除外されてしまいます。
- 6:49値がない場合だけを除きたいなら、ヌルとアンディファインドを明示的に判定します。
- 6:54第二に、ヌルのタイプオブはオブジェクトになります。
- 6:58プロパティに触れる前に、ヌルを先に除外してください。
- 7:01第三に、イン演算子は継承したプロパティにも反応します。
- 7:05形の確認と、自分のプロパティだけを許可する厳密な検証は、目的が違う点に注意しましょう。
- 7:11そして、非ヌルアサーションで警告だけを消すと、値がない場合の扱いという判断がコードに残りません。
- 7:17決めた扱いを、コードとして書きましょう。
- 7:20まとめです。
- 7:21ユニオン型は候補を縦棒で列挙し、各候補に固有の操作は、タイプオブなどの型ガードで絞り込んでから使います。
- 7:29判別可能なユニオンでは、状態ごとに必要なデータを結び付け、スイッチの各分岐で安全に読み取れます。
- 7:37すべての分岐を処理した後に残るネバーを使えば、新しい状態の処理漏れをコンパイルエラーとして検出できます。
- 7:45外部入力はアンノウンで受け取り、型述語を持つ検証を通してから使います。
- 7:51型による確認と、実行時の検証は別のものだという区別も大切です。
- 7:56次回は第七回として、ジェネリクスを学びます。
- 7:59お疲れさまでした。
この動画で学べること
TypeScriptのユニオン型と型ガードを配送状態の実装で解説。typeof、unknownの検証、判別可能なユニオン、neverによる処理漏れの確認を学びます。
解説記事・サンプルコードを読む:TypeScriptのユニオン型と型ガード:型の絞り込みからneverによる網羅チェックまで →