問題 & 解答
https://github.com/type-challenges/type-challenges/blob/main/questions/00898-easy-includes/README.md
JavaScriptのArray.includes
を型で実装する。
はじめはこういう回答を考えました。
が、全然ダメでした…。
全然わからなかったので、今回は答えを見ました。見つけた回答がこちら
https://github.com/type-challenges/type-challenges/issues/1568
順番に読み下していきます。
型Includes
は第1引数(配列)、第2引数を受けます。
inferキーワードとVariadic Tuple Typesを利用して、配列Tの最初の要素の型情報をFirst
として、以降の要素がある場合にそれらの型情報をRest
として推論します。
以下はそれぞれinferとVariadic Tuple Typesが出た回です。
https://ikuma-t.work/posts/type-challenge-first-of-array
https://ikuma-t.work/posts/type-challenge-concat
Conditional Typesの一つ目の分岐で一旦脳をセーブします。ここの部分で、なんらかの配列であればtrue
、そうでなければfalse
を返す型になります。 ここから始まるRecursiveな型探索のbase caseです。
では次に進みます。
Equal型はtype-challengeがutilityとして定義している独自の型で、次のように定義されています。
ちょっとここを読むのは時間がかかりそうなので、一旦は「XとYの型が同じかどうかを判定する」と認識しておきます。
https://zenn.dev/razokulover/articles/890102685d5ea2
https://github.com/microsoft/TypeScript/issues/27024
https://stackoverflow.com/questions/68961864/how-does-the-equals-work-in-typescript
話を戻します。
先程infer
で推論されたFirst
と、ジェネリクスU
が等しいかをチェックし、同じであればtrue
、そうでなければ残りのパラメータを使用して同じ処理を実施します。
一致する型が存在するまで要素を探索し、見つからなかった場合にはfalse
が返るという仕組みでした。
調べたこと
Array.prototype.includes
特定の要素が配列に含まれているかどうかをbooleanで返すメソッド。 第2引数で検索を開始するインデックスを指定することができる(省略可能)。
感想
今日はめちゃくちゃ難しかったです…。type-challengeでユーティリティとして提供されている型Equals
を使っていましたが、実質2個定義しないと解けなかった訳ですね。
Equals
のところを、シンプルにFirst extends U
とか[First, U] extends [U, First]
とか試してみたんですが、readonly
を抜けられなかったり、boolean
にfalse
が通ってしまったりと、意外と抜け漏れがあり、これはTypeScriptの内部的な比較を知らないと解けないなあと思いました。
TypeScriptなにもわからん…。
あと問題に載っているサンプルがなぜかジョジョだったのですが、作者の方は日本人の方でした。