WEBVTT

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

2
00:00:00.923 --> 00:00:04.615
タイプスクリプト入門、第七回はジェネリクスです。

3
00:00:04.615 --> 00:00:07.691
前回はユニオン型と型ガードを学びました。

4
00:00:07.691 --> 00:00:14.614
今回は、引数と戻り値などの型の関係を保ちながら、同じ処理を複数の型で使う仕組みを学びます。

5
00:00:14.614 --> 00:00:22.766
何でも許すエニー型に置き換えると、型の情報が消えて、存在しないメソッドを呼ぶ誤りも見つけられなくなります。

6
00:00:22.766 --> 00:00:30.458
ジェネリクスなら、文字列を渡せば文字列が返り、数値を渡せば数値が返る、という関係をそのまま表せます。

7
00:00:30.458 --> 00:00:35.226
型パラメータと型推論、エクステンズによる制約、キーオブによるキーの制限、

8
00:00:35.226 --> 00:00:39.995
そして外部入力の検証まで、順に確認していきましょう。

9
00:00:39.995 --> 00:00:44.072
型パラメータは生成されるジャバスクリプトには残らず、実行時には通常の関数として動く点も、

10
00:00:44.072 --> 00:00:48.148
最後に押さえます。

11
00:00:48.148 --> 00:00:49.465
まず基本の形です。

12
00:00:49.465 --> 00:00:53.417
値をそのまま返すアイデンティティ関数で見てみましょう。

13
00:00:53.417 --> 00:01:00.881
関数を定義するときに書く山括弧のティーが型パラメータ、呼び出しで指定する山括弧の文字列型が型引数です。

14
00:01:00.881 --> 00:01:04.467
引数と戻り値の両方に同じティーを使うことで、入れた値の型がそのまま返る、

15
00:01:04.467 --> 00:01:08.052
という関係を表しています。

16
00:01:08.052 --> 00:01:14.199
文字列を渡した戻り値は文字列型なので、文字列専用の大文字化メソッドを安全に呼べます。

17
00:01:14.199 --> 00:01:19.761
ティーは慣習的な名前で、ティーバリューなど別の名前に変えても動作は同じです。

18
00:01:19.761 --> 00:01:22.688
型を一か所で結び付けるのがポイントです。

19
00:01:22.688 --> 00:01:25.743
型引数は、多くの場合、省略できます。

20
00:01:25.743 --> 00:01:30.324
渡した引数からコンパイラが型を推論してくれるからです。

21
00:01:30.324 --> 00:01:37.112
文字列を渡せば、その戻り値には文字列としての操作が使え、長さは五と表示されます。

22
00:01:37.112 --> 00:01:44.239
数値を渡せば、数値専用のメソッドで小数第一位まで表示でき、結果は百二十三点ゼロです。

23
00:01:44.239 --> 00:01:54.591
なお、定数に直接渡した場合などでは、広い文字列型ではなく、特定の文字列そのものを表すリテラル型が推論されることもあります。

24
00:01:54.591 --> 00:02:00.870
逆に、文字列に対して数値専用のメソッドを呼ぼうとすると型エラーになります。

25
00:02:00.870 --> 00:02:06.300
戻り値をエニー型にしてしまうと、こうした確認は働かなくなります。

26
00:02:06.300 --> 00:02:10.427
次に、配列の先頭を取り出す共通関数を作ります。

27
00:02:10.427 --> 00:02:19.219
引数をリードオンリーの配列として受け取ると、配列としての操作と、要素の型との関係を同時に表せます。

28
00:02:19.219 --> 00:02:22.808
読み取り専用の配列も渡せるのが利点です。

29
00:02:22.808 --> 00:02:25.858
ただし、戻り値には注意が必要です。

30
00:02:25.858 --> 00:02:32.677
配列が空かもしれないため、戻り値は要素の型かアンディファインド、となります。

31
00:02:32.677 --> 00:02:38.239
型パラメータを使っても、配列に値が存在する保証は生まれません。

32
00:02:38.239 --> 00:02:45.776
空の配列では結果がアンディファインドになり、ヌル合体演算子で、なし、と表示されます。

33
00:02:45.776 --> 00:02:49.723
要素がある場合は先頭の、あかり、が返ります。

34
00:02:49.723 --> 00:02:54.568
呼び出し側で、値がない場合を必ず扱う設計にしましょう。

35
00:02:54.568 --> 00:02:59.099
オブジェクトのプロパティを安全に取り出す関数も作れます。

36
00:02:59.099 --> 00:03:02.173
ここでは型パラメータが二つ登場します。

37
00:03:02.173 --> 00:03:05.085
対象の型ティーと、キーの型ケーです。

38
00:03:05.085 --> 00:03:10.587
ケーには、ティーが持つキーの集合であるキーオブによる制約を付けます。

39
00:03:10.587 --> 00:03:17.545
これにより、指定できるキーは、そのオブジェクトに実際に存在するキーだけに制限されます。

40
00:03:17.545 --> 00:03:20.943
存在しないキーを渡すと型エラーになります。

41
00:03:20.943 --> 00:03:25.473
戻り値の型は、選んだキーの先の型を表す表記で決まります。

42
00:03:25.473 --> 00:03:31.784
名前のキーを選べば戻り値は文字列型になり、結果として、あかり、が表示されます。

43
00:03:31.784 --> 00:03:36.476
キーと値の型の対応関係を保てるのが、この書き方の強みです。

44
00:03:36.476 --> 00:03:41.744
制約がない型パラメータでは、その値にレングスがあるとは限りません。

45
00:03:41.744 --> 00:03:45.735
長さを使いたいなら、エクステンズで制約を付けます。

46
00:03:45.735 --> 00:03:52.759
数値のレングスを持つこと、という条件を課すと、その範囲内でのみレングスを安全に読めます。

47
00:03:52.759 --> 00:04:00.421
文字列や配列はこの条件を満たすので使えますが、レングスを持たない数値を渡すと型エラーになります。

48
00:04:00.421 --> 00:04:06.168
実際に文字列を渡すと、長さの十が表示され、元の文字列がそのまま返ります。

49
00:04:06.168 --> 00:04:12.553
制約は、処理に必要な性質を示してから、そのプロパティを利用するための仕組みです。

50
00:04:12.553 --> 00:04:16.704
要求は必要最小限に絞るほど、使える値の幅が残ります。

51
00:04:16.704 --> 00:04:18.708
ここからは外部入力の話です。

52
00:04:18.708 --> 00:04:22.357
ジェイソンを読み込むとき、パースの結果をアズで型断定して返すだけの関数では、

53
00:04:22.357 --> 00:04:26.007
構造は何も確認されません。

54
00:04:26.007 --> 00:04:32.304
型引数にユーザー型を指定しても、入力に必要なプロパティが追加されるわけではないからです。

55
00:04:32.304 --> 00:04:36.741
そこで、検証する関数自体を別の引数として受け取る設計にします。

56
00:04:36.741 --> 00:04:41.178
パース結果はまずアンノウンとして受け取り、検証関数に渡します。

57
00:04:41.178 --> 00:04:48.191
戻り値の型は検証関数の戻り値から推論されるので、呼び出し側では、検証済みの型として安全に使えます。

58
00:04:48.191 --> 00:04:51.697
ジェネリクスは型の関係を表す仕組みであり、実行時の検証の代わりにはならない、

59
00:04:51.697 --> 00:04:55.204
という区別が大切です。

60
00:04:55.204 --> 00:04:57.601
検証関数の中身を見てみましょう。

61
00:04:57.601 --> 00:05:05.090
まず、値がオブジェクトであること、ヌルでないこと、アイディーと名前の項目が存在することを確認します。

62
00:05:05.090 --> 00:05:12.131
次に、アイディーが数値であり、正の整数であること、名前が空でない文字列であることまで調べます。

63
00:05:12.131 --> 00:05:14.977
一つでも満たさなければ例外を投げます。

64
00:05:14.977 --> 00:05:19.770
最後に、必要な項目だけを持つ新しいオブジェクトを作って返します。

65
00:05:19.770 --> 00:05:25.912
名前が取れることだけでなく、業務上の条件まで実行時に確認している点がポイントです。

66
00:05:25.912 --> 00:05:30.106
ただし、ジェネリクスは検証関数の正しさまで証明しません。

67
00:05:30.106 --> 00:05:33.402
不正な入力のテストも合わせて用意しましょう。

68
00:05:33.402 --> 00:05:40.592
条件を一つにまとめず、項目ごとに分けて書くことで、どの確認で弾かれたかが読み取りやすくなります。

69
00:05:40.592 --> 00:05:42.897
実際に動かして確かめましょう。

70
00:05:42.897 --> 00:05:46.277
正しいジェイソンを検証関数と一緒に渡すと、ユーザーの名前である、あかり、

71
00:05:46.277 --> 00:05:49.657
が表示されます。

72
00:05:49.657 --> 00:05:54.421
一方、アイディーがゼロのデータ、名前が欠けたデータ、空白だけの名前のデータは、

73
00:05:54.421 --> 00:05:59.184
いずれも形式が正しくないとして例外になります。

74
00:05:59.184 --> 00:06:05.176
ジェイソン自体の構文が壊れている場合は、パースの段階で別の例外が投げられます。

75
00:06:05.176 --> 00:06:10.093
つまり、構文の不正と構造の不正は、別の場所で検出されるわけです。

76
00:06:10.093 --> 00:06:15.625
コンパイルはストリクトと、添字アクセスのチェックを有効にして行い、生成されたジャバスクリプトをノードで実行して、

77
00:06:15.625 --> 00:06:21.156
表示と例外の両方を確認しました。

78
00:06:21.156 --> 00:06:25.513
すべての関数をジェネリクスにする必要はありません。

79
00:06:25.513 --> 00:06:31.439
判断の基準は、入力の型を戻り値や別の引数に結び付けたいかどうかです。

80
00:06:31.439 --> 00:06:38.062
たとえば、文字列配列と数値配列で結果の型も対応させたい場面が対象になります。

81
00:06:38.062 --> 00:06:46.079
逆に、文字列の長さだけを返すなら、引数を文字列型、戻り値を数値型とする単純な関数で十分です。

82
00:06:46.079 --> 00:06:53.399
また、型エラーをアズで消す前に、その操作がすべての型で成立するかを確認してください。

83
00:06:53.399 --> 00:06:58.802
必要なプロパティがあるなら制約を追加し、外部入力なら検証する。

84
00:06:58.802 --> 00:07:03.856
根拠のない断定は、関係が正しくない実装を隠してしまいます。

85
00:07:03.856 --> 00:07:04.884
まとめです。

86
00:07:04.884 --> 00:07:12.081
ジェネリクスは、引数と戻り値などの型の関係を保ちながら、処理を共通化する仕組みです。

87
00:07:12.081 --> 00:07:19.450
定義側の型パラメータと呼び出し側の型引数を区別し、通常は型推論に任せて簡潔に書きます。

88
00:07:19.450 --> 00:07:24.933
配列の先頭のように値がない可能性は、戻り値の型に正直に表します。

89
00:07:24.933 --> 00:07:31.273
キーオブとエクステンズによる制約で、キーや必要なプロパティを制限できます。

90
00:07:31.273 --> 00:07:36.928
一方、ジェイソンのような外部入力は、型引数だけでは検証できません。

91
00:07:36.928 --> 00:07:41.726
アンノウンを受け取り、検証を通してから使うのが原則です。

92
00:07:41.726 --> 00:07:48.581
制約で要求する項目は、処理に必要な範囲に絞ることが、共通化の効果を保つコツです。

93
00:07:48.581 --> 00:07:51.494
これで実践連載の第七回は完了です。

94
00:07:51.494 --> 00:07:53.036
お疲れさまでした。
