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をどうぞ
型パズルやってみよう
難易度順にいくつか用意されているので、easyから1つやってみることにします。
雑に問題を訳すと皆さんご存知?の Pick<T, K>
型を自分で書いてみようになります
Take the Challenge
をクリックすると 問題が記載されたts playgroundが出てきます。
回答
Pickのおさらい
interface Todo {
title: string
description: string
completed: boolean
}
type p = Pick<Todo, 'title'>
// pの型は↓になる
type p = {
title: string;
}
回答↓
説明
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が存在するオブジェクトの型です。
参考
Discussion