TypeScriptで型パズルを始めてみよう
はじめに
TypeScript の高度な型システム学びたいけど
- 何からやればいいのか
- たまに使うけど忘れる
といった方におすすめのものを見つけました
社内 LT で発表したものを編集した記事になります。
type-challenges
This project is aim to help you better understand how the type system works, writing your own utilities, or just having fun with the challenges. このプロジェクトの目的は、型システムがどのように動作するかをよりよく理解したり、独自のユーティリティを書いたり、あるいはチャレンジを楽しんだりすることです。
詳しくは type-challenges の README か下記の qiita をどうぞ https://qiita.com/ryo2132/items/925b96838dd8cca7cebd
型パズルやってみよう
難易度順にいくつか用意されているので、easy から 1 つやってみることにします。
雑に問題を訳すと皆さんご存知?の Pick<T, K>
型を自分で書いてみようになります
https://github.com/type-challenges/type-challenges/blob/master/questions/4-easy-pick/README.md
Take the Challenge
をクリックすると 問題が記載された ts playground が出てきます。
回答
Pick のおさらい
interface Todo {
title: string;
description: string;
completed: boolean;
}
type p = Pick<Todo, "title">;
// pの型は↓になる
type p = {
title: string;
};
回答 ↓
回答 TypeScript playground が開きます
説明
type MyPick<T, K extends keyof T> = {
[p in K]: T[p];
};
K extends keyof T
の説明
keyof T で T の union Type が取得できる
K extends keyof T
は K が keyof T
型でないと駄目なことを表している。
[P in K]: T[P]
の説明
mapped type と呼ばれる型です。 簡単に説明すると
{[P in K]: T[P]}という型の意味は、「K 型の文字列 P に対して、型 T[P]を持つプロパティ P が存在するようなオブジェクトの型」
です。 難しいですね。
今回の場合だと
type MyPick<T, K extends keyof T> = {
[p in K]: T[p];
};
type mp = MyPick<Todo, "title">;
T が Todo 型、K が Todo 型の key の union type 'title' | 'completed' | 'description'
となります。
つまり、 'title' | 'completed' | 'description'
型の文字列 P に対して、型 Todo['title' | 'completed' | 'description']
をもつプロパティ P が存在するオブジェクトの型です。
参考 https://qiita.com/ryo2132/items/925b96838dd8cca7cebd https://qiita.com/uhyo/items/e2fdef2d3236b9bfe74a#conditional-types