generated at
IsUnion<T>
T がunion型かどうかを判断して true or false を返す



使用例
ts
type case1 = IsUnion<string> // false type case2 = IsUnion<string|number> // true type case3 = IsUnion<[string|number]> // false



定義時の考え方
「Union型かどうか?」の判定をしたい
.. extends .. で条件分岐したいが、直接的にUnion型かどうかを判定する方法がない
そこで「Union型特有の機能はなんだっけ?」を考える
ここでDistributive Conditional Typesを思い出す
Union型なら .. extends を使うと分配され、そうでなければ分配されない
分配された個々を、元の型と比較して、同じかどうかを確かめればいい
例えば、Union型以外の時、
分配前は string 、分配後も string で同じになる
例えば、Union型の時、
分配前の a|b|c で、分配後は a で異なるものになる
そこで無理やり分配させるためにU extends Uを使う
次に、分配前と分配後を比較する必要がある
しかし、普通に 分配後 extends 分配前 と書くと常に真になってしまう
そこで、反転して書きたい 分配前 extends 分配後
しかし、 a|b|c extends a の様に書くと、再び a|b|c が分配されてしまうので困る
そこで[U] extends ..でdistributeを避けるを使って分配を防ぐ
結果的に 分配前[] extends 分配後[] とする
これで判断できる




定義1
ts
type IsUnion<T, U = T> = T extends T ? ([U] extends [T] ? false : true) : never;
型引数の U は、「分配前の T 」が欲しいために定義している



定義2
定義1とほぼ同じだが、ちょっとスマート
ts
type IsUnion<T> = T[] extends (T extends T ? T[] : never) ? false : true;
(..) の部分は
UnionからUnionへの型レベルmapをして、 T の配列のUnion型に変換
T[] extends .. の部分は普通に考えればわかるmrsekut



定義3
ts
type IsUnion<T, U = T> = T extends T ? Not<Equal<T, U>> : never;
定義1とほぼ同じ