Open2
Typescript型パズルスクラップ

type Includes<T extends readonly any[], U> =
T extends [infer K, ...infer Rest] ?
[K, U] extends [U, K] ?
Equal<U, K>
: Includes<Rest, U>
: false
以下LLMが解答
このTypeScriptのコードは、Includes<T, U>
という型を定義しています。この型は、配列型 T
に型 U
が含まれているかどうかを判定します。少し複雑ですが、一つずつ説明します。
コードの解説
-
型パラメータ:
type Includes<T extends readonly any[], U>
-
T
は配列型であり、readonly any[]
を継承しています。これは、読み取り専用の任意の型の配列であることを意味します。 -
U
は配列T
に含まれているかどうかをチェックする対象の型です。
-
-
条件分岐 (条件付き型):
T extends [infer K, ...infer Rest] ?
- ここで、
T
が少なくとも1つの要素を持つかどうかを確認しています。 -
T
が[infer K, ...infer Rest]
に一致する場合、T
の最初の要素がK
に、残りの要素がRest
に割り当てられます。 - もし
T
が空の配列である場合、この条件はfalse
になります。
- ここで、
-
要素の比較:
[K, U] extends [U, K] ?
- これは、
K
とU
が同じ型かどうかを確認するためのチェックです。 -
K
とU
が同じ型であれば、次のステップに進みます。
- これは、
-
型の等価性チェック:
Equal<U, K>
-
Equal<U, K>
は、U
とK
が厳密に同じ型であるかを判定する型です。この型がtrue
になる場合、U
がT
に含まれていると判断します。
-
-
再帰的処理:
: Includes<Rest, U>
- もし
K
とU
が異なる型である場合、T
の残りの要素 (Rest
) に対して同じ処理を再帰的に行います。
- もし
-
終了条件:
: false
-
T
が空になった場合(つまり、全ての要素を確認してU
が見つからなかった場合)、結果はfalse
になります。
-
まとめ
この型 Includes<T, U>
は、次のように動作します:
-
T
の最初の要素とU
が同じ型かどうかを確認し、同じならtrue
を返します。 - 違う場合は、
T
の残りの部分で再帰的に同じチェックを行います。 -
T
が空になるとfalse
を返します。
これによって、配列 T
に型 U
が含まれているかどうかを判定することができます。
例えば:
type Test1 = Includes<[1, 2, 3], 2>; // true
type Test2 = Includes<[1, 2, 3], 4>; // false
このように、Includes
は T
に U
が含まれているかどうかを正確に判断します。

type Equal<X, Y> = (<T>() => T extends X ? 1 : 2) extends <T>() => T extends Y ? 1 : 2 ? true : false
以下LLM解答
このTypeScriptのコードは、Equal<X, Y>
という型を定義しており、2つの型 X
と Y
が「厳密に」等しいかどうかを判定します。少し複雑に見えるかもしれませんが、各部分を分解して説明します。
コードの解説
-
型パラメータ:
type Equal<X, Y>
-
X
とY
は比較される2つの型です。この2つの型が等しいかどうかを確認します。
-
-
条件付き型とジェネリック関数の定義:
(<T>() => T extends X ? 1 : 2)
- ここで、ジェネリック型
T
を持つ無名関数(アロー関数)が定義されています。 -
T
がX
に代入可能かどうかを判定しています。もしT
がX
に代入可能ならば1
を返し、そうでなければ2
を返します。
- ここで、ジェネリック型
-
型の比較:
extends <T>() => T extends Y ? 1 : 2
- 先ほどの関数の型が、
T
がY
に代入可能かどうかをチェックする別の無名関数と比較されます。 -
X
とY
の両方に対して同じチェックを行うことで、これらの型が等しいかどうかを間接的に比較しています。
- 先ほどの関数の型が、
-
結果の判定:
? true : false
- 上記の比較が真であれば
true
を返し、そうでなければfalse
を返します。
- 上記の比較が真であれば
仕組みの詳細
- このコードは、「ジェネリック型の条件付き型推論」を利用しています。具体的には、型
X
とY
の両方を使って、無名ジェネリック関数の返り値型が一致するかどうかを確認します。 - もし
X
とY
が完全に同じ型であれば、T
がX
に代入可能である条件と、T
がY
に代入可能である条件は一致するため、両方とも同じ結果(1
または2
)を返します。 - そのため、
<T>() => T extends X ? 1 : 2
と<T>() => T extends Y ? 1 : 2
は同じ型になり、Equal<X, Y>
はtrue
を返します。
逆に、X
と Y
が異なる型であれば、関数の返り値型が異なるため、Equal<X, Y>
は false
を返します。
例
type Test1 = Equal<1, 1>; // true
type Test2 = Equal<1, 2>; // false
type Test3 = Equal<{ a: string }, { a: string }>; // true
type Test4 = Equal<{ a: string }, { a: number }>; // false
これらの例から分かるように、Equal<X, Y>
は、X
と Y
が同じ型かどうかを正確に判定する型です。