問題 & 解答
組み込みのExclude<T, U>
を自前で実装する
Conditional Typesの分配法則を用いて、次のように記述する。
type MyExclude<T, U> = T extends U ? never : T
例えば
T
:"a" | "b" | "c" | "d"
U
:"c" | "d" | "e" | "f"
であるとき、まず"a"
はU
のサブセットではないので、T
つまり"a"
が返る。
一つ飛ばして"c"
はU
のサブセットなので、never
が返る。
分配法則によりこれらの結果を結合したものが返るのでMyExclude<"a" | "b" | "c" | "d", "c" | "d" | "e" | "f">
は"a" | "b"
をあらわす
調べたこと
Exclude型
差集合を表す型
// Exclude<UnionType, ExcludedMembers>
// (a, b, c)type T0 = Exclude<"a" | "b" | "c", "a">// type T0 = "b" | "c"
type T1 = Exclude<"a" | "b" | "c" | "d", "c" | "d" | "e" | "f">// type T1 = "a" | "b"
TypeScript: Documentation - Utility Types🔗
Conditional TypesとDistributive(分配法則)
- Conditional types がGeneric型である時、Union型が渡された場合は、分配法則に従う。
// 各Tがanyでを満たせば`T[]`を返すtype ToArray<T> = T extends any ? T[] : never;
type StrArrOrNumArr = ToArray<string | number>;
StrArrOrNumArr
では、T
としてUnion型のstring | number
が与えられている。
// StrArrOrNumArrの右辺は次のようになる(ちょっと表現としては変だけど)(string | number) extends any ? T[] : never
// 分配法則により次のように読み下せる(string extends any ? string[] : never) | (number extends any ? number[] : never)
// anyはすべてを満たすので`StrArrOrNumArr`はこうなるstring[] | number[]