type-challengeをやっていてまた自分がこれまで目を背けてきたものがあったのでここでアウトプットします。
それはConditional Type
です。
ちなみに自分が全くわからなかったのが以下の問題です
問題は
配列Tを受け取り、その最初のプロパティの型を返すFirstを実装します。
というもの
[3, 2, 1],
[() => 123, { a: string }],
[],
[undefined],
上記がテストとして渡されて型に0番目の値が渡ってくれば合格というものでした。
自分は迷いに迷って以下のようになりましたが、nullとundefinedのテストがエラーになりました。
type First<T extends (string | number | (() => number | null | undefined))[]> = T[0]
答えは以下です。
type First<T extends any[]> = T extends { length: 0 } ? never : T[0]
T extends { length: 0 } ? never : T[0]
これがconditional typeと呼ばれるものです。
Conditional Typesは読んで字の如く、型定義における条件分岐です。次の構文で表現します。
type MyCondition<T, U, X, Y> = T extends U ? X : Y;
観察
- 三項演算子が使われています。
extends
を知っていればいけそうです。
- ジェネリクスに4種類の型T,U,X,Yが渡されています。
これを読み解くと
T型がUに内包されていれば、X
型を使用
そうでなければY
型を使用
ということになります。
自分がわからなかった問題の答えを見てみます。
type First<T extends any[]> = T extends { length: 0 } ? never : T[0]
まず左辺にはany
[]として配列であればなんでも渡せるというかなり緩めの制約
がついています。
次に右辺には渡された型Tのlengthが0であればnever
型を返し、そうでなければ型の一番最初のものを返すとしています。
ここで {length: 0}
はどこからきたのか疑問が湧きました。
これについてはざっと調べたのですが、TypeScriptでの情報をうまく集めることができなかったので見つけたら記事化します。
参考
強くなりたい!!!!!!!