タイムリープTypeScript 〜TypeScript始めたてのあの頃に知っておきたかったこと〜 Advent Calendar 2021 22日目です。
type-challengesを二週間続けてみた
というタイトルで書いていきます。
何度か話題になっていますが、type-challengesはTypeScriptの型パズルに挑戦できるリポジトリです。
VueやNuxt、Viteなどのコアメンバーである、@antfu7さんを中心に開発されています。
僕自身TypeScriptは仕事で使うものの、型の読解力や実装力に苦手意識があったので思いきって取り組むことにしました。
この記事では僕が二週間type-challengesに取り組んできて思ったことを書きたいと思います。
そもそもtype-challengesとは、については@KawamataRyoさんのこちらの記事がわかりやすいです。
進め方
現状の自分なりの進め方です。
- 1日1問
- READMEから順番に解いていく
- 基本5分以内で解く
- 解くに当たって参考にしたドキュメントなどは問題と一緒にメモしておく
無理なく続けたかったので一日一問を解くようにしています。
僕は長く考えてもだれてしまうタイプなので5分間手が何も動かなかったら解答を見てしまっています。(答えは出ていなくても手が動いているなら続ける)
また何を解くか悩みたくないのでREADMEに載っている順番に解くようにしています。
参考にしたドキュメントや記事などはplaygroundのurlと共にメモに保存するようにしています。
二週間やってみて
二週間続けてみて以下のようなことを感じました。
<T>
のような記述に抵抗がなくなった
TypeScriptを始めた頃に最初によくわからなくなるポイント第1位、Genericsです。
type-challengesではほぼ全ての問題でGenericsを使用します。
雰囲気で使っていましたが、理解して使えるようになったと思います。
https://www.typescriptlang.org/docs/handbook/2/generics.html
{ [P in K]: T }
のような記述に抵抗がなくなった
実際のコードでも非常によく使われている、Mapped Types
と呼ばれる型記法です。 (Mapped types #12114 )
Pは識別子、Kは文字列に割り当て可能な型、TはPを型パラメータとして使用可能な型となっています。
type Item = { a: string, b: number, c: boolean };
type T1 = { [P in "x" | "y"]: number }; // { x: number, y: number }
type T2 = { [P in "x" | "y"]: P }; // { x: "x", y: "y" }
type T3 = { [P in "a" | "b"]: Item[P] }; // { a: string, b: number }
type T4 = { [P in keyof Item]: Date }; // { a: Date, b: Date, c: Date }
type T5 = { [P in keyof Item]: Item[P] }; // { a: string, b: number, c: boolean }
type T6 = { readonly [P in keyof Item]: Item[P] }; // { readonly a: string, readonly b: number, readonly c: boolean }
type T7 = { [P in keyof Item]: Array<Item[P]> }; // { a: string[], b: number[], c: boolean[] }
type-challengesでも一番最初の問題であるeasyのPickでいきなり使われていて死にました。
never型への理解が深まった
よく型エラー時に出会っていたnever型ですが、よくわからないまま通り過ぎていました。
type-challengesを解くに当たって結構な頻度で使う場面が出てくるのでこれを機にしっかり勉強しました。
このあたりがとてもわかりやすかったです。
https://numb86-tech.hatenablog.com/entry/2020/02/06/214324
type-challengesではeasyのFirst of Arrayで初登場した記憶があります。
Conditional Typeへの理解が深まった
存在は知っていたものの使ったことがなかったConditional Type。
型の条件分岐ができる記法です。こちらも問題内でかなり使用されています。
SomeType extends OtherType ? TrueType : FalseType;
JavaScriptの三項演算子のような記述で書くことができ上記の例だと、
SomeTypeがOtherTypeに代入可能であれば、TrueTypeを返し、そうでなければFalseTypeを返す
といった記述となります。
公式ドキュメントがとてもわかりやすいです。
type-challengesではeasyのFirst of Arrayで初登場します。
知らなかったことを知る機会になった
今回は取り上げませんでしたが、問題を通してinferやIndexed Access Typesなど全く知らなかったTypeScriptの型に関することを多く学べました。
まとめ
僕は以前にもtype-challengesに挑戦していたのですが、1問目のPickに見事洗礼を受けて撃沈し一度挫折していました。
ただ今回から5分ルールを作り、わからなかったら解答を見て理解して次に進むというやり方をとったため、無理なく続けてられています。
結果、mediumレベルの問題も解けるものが増えてきています。
TypeScriptで開発されているチームリポジトリやOSSにふんだんに使用されている記述を理解できるようになったことは大きいなと感じているのでこれからも続けていきたいです。
おまけ
type-challengesを解くにあたりよく参考にしている書籍等を載せておきます。
-
公式ドキュメント
- 英語ですが、よくわからない部分は翻訳したり、さらにググったりしています。
-
プログラミングTypeScript - O'Reilly Japan
- 評判が良いオライリーのTS本です。TSについて網羅的に書かれています。
-
Type Challenges Solutions
- リポジトリの解答集を見てもわからない時にこちらを見にいきます。かなり丁寧に解説されていてありがたい🙏