今更type-challengesをやる -初級編②-

type-challengesを解いていくやつ第2回。今回は初級編の続きです。
前回はこちら。

karakasadcfd.hatenablog.com

If

3つの型引数C,T,Fを受け取り、CtrueならTを、CfalseならFを返す型Ifを実装してみようという問題。
単純に型Ctrueなのかfalseなのか判別できればいいが、型の世界の話なのでどう記述するかがポイントっぽい。
このような型による条件分岐をしたい時はConditional Typesと呼ばれるものを使えばいい。

www.typescriptlang.org

通常の三項演算子における条件文でextendsを使用するだけなので、知っていればなんということはなかった。

type If<C extends boolean, T, F> = C extends true ? T : F

Awaited

Promise<T>を受け取ってTを取り出して返す型を実装しようという問題。
Promise<T>からTを取り出すという部分をどう記述するかがポイントっぽい。
これにはinferを使えば良さそう。inferはConditional Typesのextends節の中で使用することで型を推論することができ、推論した型を型引数として導入できる。この機能については公式ドキュメントのAdvanced Typesの中で述べられている。

www.typescriptlang.org

今回の問題の場合はT extends Promise<infer R>のような形で記述すればTがなんらかのPromiseであるときに、それが内包する具体的な型を型変数Rとして扱うことができるようになる。

type MyAwaited<T extends Promise<any>> = T extends Promise<infer R> ? R : never

inferは色々悪さができそうなので、今後の問題でもめちゃくちゃ使いそうな予感。

Concat

Array.concatの型バージョンを実装しようという問題。
前回のPushやUnshiftと同様、Variadic Tuple Typesを使うだけ。

www.typescriptlang.org

type Concat<T extends any[], U extends any[]> = [...T, ...U]

First of Array

配列Tを受け取り、その最初のプロパティの型を返すFirst<T>を実装しようという問題。
前回も活躍したインデックスアクセス型を使えば、配列の最初のプロパティの型はT[0]と書くだけで取り出せそう。

typescriptbook.jp

しかし空配列を渡された場合はこのようなプロパティが存在しないためエラーとなるので、空配列か空でない配列かで条件分岐する必要があるのがミソっぽい。

type First<T extends any[]> = T extends [] ? never : T[0]

Includes

Array.includeの型バージョンを実装しようという問題。
配列の中に特定の要素が含まれているかを判定するために、まず配列の要素の型をユニオン型で取得したい気持ちになる。これは前回Tuple to Objectでも同じような気持ちになったので、今回もインデックスアクセス型が活躍する。前の問題(First of Array)のようにT[0]と具体的な数値を指定するのではなく、T[number]のように記述することで要素の型をユニオン型で取得できる。

type Includes<T extends readonly any[], U> = U extends T[number] ? true : false

Parameters

TypeScript組み込みのユーティリティ型であるParameters<T>を自分で実装してみようという問題。
Parameters<T>は受け取った関数型の引数の型をタプルで返す型なので、渡された関数の型から引数部分だけをどうにか取り出す必要がありそう。ある型が内包する具体的な型を取得したいといえばAwaitedの問題でも同じ気持ちになったので、ここでもinferに頑張ってもらう。

type MyParameters<T extends (...args: any[]) => any> = T extends (...args: infer R) => any ? R : never

ここまでの感想

今回はConditional Typesのチュートリアル的な感じなのか、型の条件分岐を必要とする問題が中心の構成だった。さらにinferも登場して、今後の問題でもたくさん活躍してくれそうな武器が手に入った回だった。
次は中級編の方に入っていこうと思う。

ところで......

色々見ているうちに気付いたのだが、どうやら本家type-challengesが提供するPlaygroundでは各問題に対して様々なテストケースが用意されており、随時追加されたりもしているらしい。ということで今まで解いた問題をチェックし直してみたが、なんとまあテストに落ちること落ちること......。やばそうなテストケースもあり、easyとはなんだったのかという気持ちが増してくる。
というわけで、次回は中級編ではなく初級編の完全解答を目指す回になりそう。(それもしかして中級編解くよりも難しかったりしないか......?)