WEBVTT

1
00:00:00.000 --> 00:00:00.932
こんにちは。

2
00:00:00.932 --> 00:00:05.129
今回のテーマは、タイプスクリプトの実践的な型設計です。

3
00:00:05.129 --> 00:00:10.335
状態の違いをユニオン型で表し、設定をサティスファイズで確かめ、外部データをアンノウンで受けて検証する、

4
00:00:10.335 --> 00:00:15.542
三つの道具の使い分けを学びます。

5
00:00:15.542 --> 00:00:20.049
舞台は、記事を取得して画面に表示する小さなプログラムです。

6
00:00:20.049 --> 00:00:26.576
大切な区別は、型チェックで確かめることと、実行時に確かめることは別だ、という点です。

7
00:00:26.576 --> 00:00:30.928
画面の状態や、コードの中で作る設定は型で守れますが、通信で届くデータの中身は、

8
00:00:30.928 --> 00:00:35.279
実行時に調べなければ分かりません。

9
00:00:35.279 --> 00:00:41.030
この線引きを意識しながら、矛盾した状態を作らない、書き間違いを早く見つける、

10
00:00:41.030 --> 00:00:46.780
危ないデータを入口で止める、という三つの効果を順に確認していきましょう。

11
00:00:46.780 --> 00:00:50.521
まず、記事そのものを表すポスト型を用意します。

12
00:00:50.521 --> 00:00:54.912
文字列のアイディーとタイトルを持つ、シンプルな形です。

13
00:00:54.912 --> 00:01:01.418
次に読み込み状態を、真偽値のローディングと、任意のデータとエラーで表してみます。

14
00:01:01.418 --> 00:01:07.110
一見便利ですが、この形では、読み込みが終わっているのにデータとエラーを両方持つ、

15
00:01:07.110 --> 00:01:12.803
といった矛盾した組み合わせまで型チェックを通ってしまいます。

16
00:01:12.803 --> 00:01:18.658
実機でも、その矛盾したオブジェクトがエラーなく作れることを確認しました。

17
00:01:18.658 --> 00:01:22.886
画面側で条件分岐を増やして取り繕う前に、そもそも許可する状態の組み合わせを、

18
00:01:22.886 --> 00:01:27.115
型の側で絞ることが大切です。

19
00:01:27.115 --> 00:01:30.368
次から、そのための書き方を見ていきます。

20
00:01:30.368 --> 00:01:33.273
解決策は、判別可能なユニオンです。

21
00:01:33.273 --> 00:01:40.964
ロードステート型は、待機中、読み込み中、成功、失敗の四つの形の、どれか一つだけを表します。

22
00:01:40.964 --> 00:01:46.091
四つに共通するステータスには、それぞれ違う文字列を入れます。

23
00:01:46.091 --> 00:01:51.901
成功の形だけが記事データを持ち、失敗の形だけがメッセージを持ちます。

24
00:01:51.901 --> 00:01:57.541
逆に言えば、成功なのにデータがない値は、この型には代入できません。

25
00:01:57.541 --> 00:02:04.719
実機でも、データなしの成功状態はエラー・ティーエス2322になることを確認しました。

26
00:02:04.719 --> 00:02:09.589
状態と、その状態で必要なデータをひも付けることで、あり得ない組み合わせ自体を作れなくするのが、

27
00:02:09.589 --> 00:02:14.460
この設計の狙いです。

28
00:02:14.460 --> 00:02:19.117
ロードステートを使う関数、ゲットラベルを見てみましょう。

29
00:02:19.117 --> 00:02:25.270
ステータスでスイッチ分岐すると、各ケースの中では型が自動で絞り込まれます。

30
00:02:25.270 --> 00:02:31.757
成功のケースではデータが必ずあると判断されるため、タイトルをそのまま読めます。

31
00:02:31.757 --> 00:02:35.748
感嘆符を付けて無理に断言する書き方は要りません。

32
00:02:35.748 --> 00:02:41.320
待機中なら記事を選んでください、読み込み中なら読み込み中、失敗ならそのメッセージを返す、

33
00:02:41.320 --> 00:02:46.891
というように、状態ごとに返せる値が決まります。

34
00:02:46.891 --> 00:02:52.962
実機で四つの状態すべてを渡すと、記事を選んでください、読み込み中、型設計の基本、

35
00:02:52.962 --> 00:02:59.032
読み込みに失敗しました、の順に表示され、記事の説明と一致しました。

36
00:02:59.032 --> 00:03:01.905
分岐の漏れを防ぐ仕掛けが、ネバーです。

37
00:03:01.905 --> 00:03:07.198
ゲットラベルのデフォルトでは、アサートネバーという関数へ値を渡します。

38
00:03:07.198 --> 00:03:10.526
この関数はネバー型の引数しか受け取りません。

39
00:03:10.526 --> 00:03:17.633
通常はすべてのケースを処理し終えるため、デフォルトに残る値はない、つまりネバーになるはずです。

40
00:03:17.633 --> 00:03:22.548
ところが新しい状態キャンセルドを追加して分岐を書き忘れると、残った値がネバーではないため、

41
00:03:22.548 --> 00:03:27.463
エラー・ティーエス2345が発生します。

42
00:03:27.463 --> 00:03:30.034
実機でも同じエラーを確認しました。

43
00:03:30.034 --> 00:03:35.327
状態を増やしたときに、直すべき場所をコンパイラが教えてくれるわけです。

44
00:03:35.327 --> 00:03:42.284
ただしこれはコード内の分岐漏れの検出であり、外部データの正しさを保証するものではありません。

45
00:03:42.284 --> 00:03:43.832
次は設定の検査です。

46
00:03:43.832 --> 00:03:48.629
ルート設定では、ホームは文字列のパス、記事一覧はパスと認証要否を持つオブジェクト、

47
00:03:48.629 --> 00:03:53.426
というように、キーごとに値の形が違います。

48
00:03:53.426 --> 00:03:59.075
ここでサティスファイズ・レコード・ページネーム・ルート、と書くと、キーがそろっているか、

49
00:03:59.075 --> 00:04:04.724
各値がルート型を満たすかを、コンパイル時に確かめられます。

50
00:04:04.724 --> 00:04:12.616
キーを打ち間違えた場合や、数値のような合わない値を入れた場合も、エラーになることを実機で確認しました。

51
00:04:12.616 --> 00:04:19.425
そのうえで、ホームは文字列として、アーティクルズはオブジェクトとして、そのまま扱えます。

52
00:04:19.425 --> 00:04:26.544
実行すると、ホームはスラッシュのまま、アーティクルズのパスは大文字に変換されて表示されます。

53
00:04:26.544 --> 00:04:28.777
型注釈との違いも押さえます。

54
00:04:28.777 --> 00:04:38.026
コロンでレコード型を注釈すると、値はその型で広く扱われ、各項目は文字列かオブジェクトか分からないルート型になります。

55
00:04:38.026 --> 00:04:46.638
そのため、文字列のメソッドを呼ぶ前に絞り込みが必要になり、実機でもエラー・ティーエス2339を確認しました。

56
00:04:46.638 --> 00:04:52.699
一方サティスファイズは、検査をしながら、書いた値本来の扱いやすさを残します。

57
00:04:52.699 --> 00:04:57.004
ただし、サティスファイズはコンパイル時の検査だけです。

58
00:04:57.004 --> 00:05:04.978
実行時の検証や、オブジェクトの凍結はしませんし、すべての値がリテラル型のまま残るわけでもありません。

59
00:05:04.978 --> 00:05:11.836
読み取り専用やリテラルとして固定したい場合は、別の仕組みと役割を分けて考えてください。

60
00:05:11.836 --> 00:05:14.216
三つ目は、外部データの扱いです。

61
00:05:14.216 --> 00:05:18.680
エーピーアイの応答は、型定義を書いただけでは保証されません。

62
00:05:18.680 --> 00:05:22.697
そこでパースポスト関数は、引数をアンノウンで受けます。

63
00:05:22.697 --> 00:05:26.863
アンノウンは、何が入っているか分からない、という型です。

64
00:05:26.863 --> 00:05:30.508
確認せずにタイトルなどを読もうとすると、エラー・ティーエス18046になり、

65
00:05:30.508 --> 00:05:34.153
実機でも確認しました。

66
00:05:34.153 --> 00:05:40.104
関数の最初では、タイプオブでオブジェクトかどうかを調べ、ヌルと配列を除外します。

67
00:05:40.104 --> 00:05:43.749
どれかに当てはまらなければ、記事データはオブジェクトである必要があります、

68
00:05:43.749 --> 00:05:47.394
というエラーを投げます。

69
00:05:47.394 --> 00:05:52.304
このように、入口で疑ってかかることが、安全な受け取りの第一歩です。

70
00:05:52.304 --> 00:05:54.915
続いて、プロパティの中身を確認します。

71
00:05:54.915 --> 00:06:01.097
イン演算子でアイディーとタイトルがあるかを調べ、タイプオブでどちらも文字列かを確認します。

72
00:06:01.097 --> 00:06:03.296
通らなければ、エラーを投げます。

73
00:06:03.296 --> 00:06:08.517
最後は、確認できた二つだけを取り出した、新しいオブジェクトを作って返します。

74
00:06:08.517 --> 00:06:11.677
余分な項目をそのまま通さない点もポイントです。

75
00:06:11.677 --> 00:06:18.272
フェッチポストでは、まずレスポンス・オッケーを確認し、失敗ならステータス付きのエラーを投げます。

76
00:06:18.272 --> 00:06:22.531
通信の結果はアンノウンとして受け取り、パースポストへ渡します。

77
00:06:22.531 --> 00:06:26.104
なお空文字の禁止や長さの制限は、型でもこの関数でも自動では決まらないため、

78
00:06:26.104 --> 00:06:29.676
必要なら別途追加してください。

79
00:06:29.676 --> 00:06:32.143
最後に、二つの仕組みをつなぎます。

80
00:06:32.143 --> 00:06:37.729
トゥーロードステート関数は、アンノウンの入力をパースポストで検証し、成功すればデータを持つサクセス状態を、

81
00:06:37.729 --> 00:06:43.316
失敗すればメッセージを持つエラー状態を返します。

82
00:06:43.316 --> 00:06:50.571
例外の受け取りでも、エラーの型はアンノウンとして扱い、エラーかどうかでメッセージの取り方を分けます。

83
00:06:50.571 --> 00:06:56.810
実機で試すと、正しい入力では見出しとして型設計の基本が表示され、アイディーが数値の入力では、

84
00:06:56.810 --> 00:07:03.049
文字列である必要があります、というメッセージが表示され、記事の期待どおりでした。

85
00:07:03.049 --> 00:07:08.128
検証と状態管理を組み合わせると、画面側は迷わず表示を切り替えられます。

86
00:07:08.128 --> 00:07:08.872
まとめです。

87
00:07:08.872 --> 00:07:12.672
状態ごとに必要なデータが変わるなら判別可能なユニオン、分岐漏れの検出にはネバー、

88
00:07:12.672 --> 00:07:16.473
コード内で作る設定の確認にはサティスファイズ、外部入力にはアンノウンと実行時の検証、

89
00:07:16.473 --> 00:07:20.273
という使い分けです。

90
00:07:20.273 --> 00:07:24.301
実行手順は、記事の五つのファイルを保存し、ストリクトなどを付けたコマンドでコンパイルして、

91
00:07:24.301 --> 00:07:28.328
生成されたジャバスクリプトを実行します。

92
00:07:28.328 --> 00:07:32.418
練習として、キャンセルドという状態を追加して分岐漏れのエラーを見つけたり、

93
00:07:32.418 --> 00:07:36.508
タイトルの空文字を禁止する検証を足したりしてみてください。

94
00:07:36.508 --> 00:07:41.961
型で守れる範囲と、実行時に確かめる範囲を分けて考える習慣が、実践的な型設計の第一歩です。

95
00:07:41.961 --> 00:07:43.076
お疲れさまでした。
