🐙

Type Challengeに入門する

2022/12/10に公開

最近ライブラリのラッパーを書くようになり、自分の型表現力の低さを痛感しているのでType Challengeに入門しようと思います。
存在自体は以前から知っていたのですが、めんどくさかったためやっていませんでした。今日から毎日最低1問取り組んでいきたいと思います。

初級・Pick

Pick<T, keys>を自作する問題です。まずPickについておさらいしておきます。

Pick<T, Keys>は、型TからKeysに指定したキーだけを含むオブジェクト型を返すユーティリティ型です。

https://typescriptbook.jp/reference/type-reuse/utility-types/pick
具体例を見ていきましょう。

typeChallenge.ts
  type Foo = {
   foo1: string;
   foo2: number;
   foo3: string;
  };
  type Hoge = Pick<Foo, 'foo1' | 'foo2'>
  // ↑は↓と同じ
  type Bar = { foo1: string; foo2: number };

つまり型引数で取るべき値は①型Tと型Tのkeyの型ですね。

typeChallenge.ts
 type MyPick<T, K extends keyof T> = {}

これで型引数の条件は満たせました。次に型を考えていきたいのですが、ここで詰まってしまいました。

typeChallenge.ts
 type MyPick<T, Keys extends keyof T> = { [Key in Keys]: T[Keys] }

これで片方のエラーは消えたのですが、もう片方のエラーが消えません。回答を確認すると、

answer.ts
 type MyPick<T, Keys extends keyof T> = { [Key in Keys]: T[Key] }

このようにしなければならなかったそうです。
T[Keys]にしてしまうと、KeysがUnion型の時にここもUnion型になってしまうんですね。今考えれば当然のことですが、やっている時は気づけませんでした。

感想

思ったより型戦闘力が低かったです。基本的なMapped Typeすら理解があやふやでした。毎日続けて少しでもマシな型戦闘力を身につけたいです。

Discussion