Open2

Typescript型パズルスクラップ

ta.toshiota.toshio

https://zenn.dev/bs_kansai/articles/87c5cde1be86b6

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 が含まれているかどうかを判定します。少し複雑ですが、一つずつ説明します。

コードの解説

  1. 型パラメータ:

    type Includes<T extends readonly any[], U>
    
    • T は配列型であり、readonly any[]を継承しています。これは、読み取り専用の任意の型の配列であることを意味します。
    • U は配列 T に含まれているかどうかをチェックする対象の型です。
  2. 条件分岐 (条件付き型):

    T extends [infer K, ...infer Rest] ?
    
    • ここで、T が少なくとも1つの要素を持つかどうかを確認しています。
    • T[infer K, ...infer Rest] に一致する場合、T の最初の要素が K に、残りの要素が Rest に割り当てられます。
    • もし T が空の配列である場合、この条件は false になります。
  3. 要素の比較:

    [K, U] extends [U, K] ?
    
    • これは、KU が同じ型かどうかを確認するためのチェックです。
    • KU が同じ型であれば、次のステップに進みます。
  4. 型の等価性チェック:

    Equal<U, K>
    
    • Equal<U, K> は、UK が厳密に同じ型であるかを判定する型です。この型が true になる場合、UT に含まれていると判断します。
  5. 再帰的処理:

    : Includes<Rest, U>
    
    • もし KU が異なる型である場合、T の残りの要素 (Rest) に対して同じ処理を再帰的に行います。
  6. 終了条件:

    : 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

このように、IncludesTU が含まれているかどうかを正確に判断します。

ta.toshiota.toshio
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つの型 XY が「厳密に」等しいかどうかを判定します。少し複雑に見えるかもしれませんが、各部分を分解して説明します。

コードの解説

  1. 型パラメータ:

    type Equal<X, Y>
    
    • XY は比較される2つの型です。この2つの型が等しいかどうかを確認します。
  2. 条件付き型とジェネリック関数の定義:

    (<T>() => T extends X ? 1 : 2)
    
    • ここで、ジェネリック型 T を持つ無名関数(アロー関数)が定義されています。
    • TX に代入可能かどうかを判定しています。もし TX に代入可能ならば 1 を返し、そうでなければ 2 を返します。
  3. 型の比較:

    extends <T>() => T extends Y ? 1 : 2
    
    • 先ほどの関数の型が、TY に代入可能かどうかをチェックする別の無名関数と比較されます。
    • XY の両方に対して同じチェックを行うことで、これらの型が等しいかどうかを間接的に比較しています。
  4. 結果の判定:

    ? true : false
    
    • 上記の比較が真であれば true を返し、そうでなければ false を返します。

仕組みの詳細

  • このコードは、「ジェネリック型の条件付き型推論」を利用しています。具体的には、型 XY の両方を使って、無名ジェネリック関数の返り値型が一致するかどうかを確認します。
  • もし XY が完全に同じ型であれば、TX に代入可能である条件と、TY に代入可能である条件は一致するため、両方とも同じ結果(1 または 2)を返します。
  • そのため、<T>() => T extends X ? 1 : 2<T>() => T extends Y ? 1 : 2 は同じ型になり、Equal<X, Y>true を返します。

逆に、XY が異なる型であれば、関数の返り値型が異なるため、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> は、XY が同じ型かどうかを正確に判定する型です。