🎃
TypeScript の Conditional Types で複数条件をマージする
TypeScript の Conditional Types 便利ですね。
この記事を読んでいる方はご存知のことと思いますが一応説明を入れておくと、Conditional Types は型定義における条件分岐です。
型 T をとって、それが文字列型と互換性があるかどうかを返す IsString は以下のように書くことができます。
type IsString<T> = T extends string ? true : false
type A = IsString<'a'> // type A = true
type B = IsString<1> // type B = false
type C = IsString<boolean> // type C = false
三項演算子のような見た目で、ネストもできます。
型 T, U をとって、それらすべてが文字列型と互換性があるかどうかを返す IsAllString は以下のように書くことができます。
type IsAllString<T, U> = T extends string
? U extends string
? true
: false
: false
type A = IsAllString<'a', 'b'> // type A = true
type B = IsAllString<'a', 2> // type B = false
type C = IsAllString<true, 'b'> // type C = false
type D = IsAllString<true, 2> // type D = false
IsAllString は実際には T と U の両方が文字列型と互換性があるかどうかを一度にチェックしたいはずですが、この例では 2 回条件分岐を使っています。
そこで Tuple を使って以下のように書き換えます。
type IsAllString<T, U> = [T, U] extends [string, string] ? true : false
type A = IsAllString<'a', 'b'> // type A = true
type B = IsAllString<'a', 2> // type B = false
type C = IsAllString<true, 'b'> // type C = false
type D = IsAllString<true, 2> // type D = false
ミソはT extends string
とU extends string
を[T, U] extends [string, string]
にまとめたところです。
これで複数の条件分岐を AND 条件としてまとめることができました。
Discussion