TL;DR

  • TypeScript を最大限に活用するための 83 項目のアドバイスを、実践的なコードとともにまとめた実用書である。
  • TypeScript の基本を身につけた初級者が、中級者、そしてエキスパートへ進むための本である。

対象読者

入門書ではない。TypeScript の基本を一通り学んだ人が、真に「effective な」TypeScript のコードを書けるようになるための本である。TypeScript は柔軟で表現力の高い型システムを持ち、JavaScript のコミュニティに広く浸透している。一方で高度な機能が多く、それらを使いこなせる開発者は多くない。本書は、適切なコードの書き方を根拠とともに示している。

目次

TypeScriptとは何か

  1. TypeScriptとJavaScriptの関係を理解する
  2. どのTypeScriptオプションが使われているか把握する
  3. コード生成は型に依存しないことを理解する
  4. 構造的型付けに慣れる
  5. any型の使用を制限する

TypeScriptの型システム

  1. エディターを使って型システムを調査、探求する
  2. 型を値の集合として考える
  3. 型空間のシンボルと値空間のシンボルの見分け方を知る
  4. 型アノテーションを型アサーションより優先的に使用する
  5. ラッパーオブジェクト型(String、Number、Boolean、Symbol、BigInt)を使用しない
  6. 余剰プロパティチェックと型チェックを区別する
  7. 可能なら関数式全体に型を適用する
  8. type(型エイリアス)とinterfaceの違いを知る
  9. readonlyを使用して変更にまつわるエラーを避ける
  10. 型演算とジェネリック型を使って重複を避ける
  11. インデックスシグネチャよりも適切な代替手段を使う
  12. 数値型のインデックスシグネチャを避ける

型推論と制御フロー解析

  1. 推論可能な型でコードを乱雑にしない
  2. 異なる型には異なる変数を使う
  3. 変数の型がどのように決まるか理解する
  4. オブジェクトを一度に構築する
  5. 型の絞り込みを理解する
  6. エイリアスを作成したら一貫してそれを使う
  7. 型推論に文脈がどう使われるか理解する
  8. 進化する型を理解する
  9. 関数型の標準APIやライブラリを使って型の流れを促進する
  10. コールバックの代わりにasync関数を使用して型の流れを改善する
  11. クラスやカリー化を使って型パラメーターを段階的に割り当てる

型設計

  1. 有効な状態のみ表現する型を作る
  2. 入力には寛容に、出力には厳格に
  3. 型情報をドキュメントで繰り返さない
  4. nullやundefinedを型エイリアスに含めない
  5. null値を型の外側に押しやる
  6. ユニオンを含むインターフェイスよりも、インターフェイスのユニオンを選択する
  7. stringよりもそれに代わる、より精度の高い型を選択する
  8. 特別な値には専用の型を使用する
  9. オプションプロパティは限定的に使用する
  10. 同じ型のパラメーターの繰り返しを避ける
  11. 差異のモデリングより型の統一を優先する
  12. 正確でない型より精度の低い型を選択する
  13. ドメインの言語を使って型を命名する
  14. たまたま目にしたデータに基づく型を避ける

不健全性とany型

  1. 可能なかぎり狭いスコープでany型を使う
  2. anyをそのまま使うのではなく、より具体的な形式で使う
  3. 安全でない型アサーションを、適切に型付けされた関数の内部に隠す
  4. 型が不明な値には、anyではなくunknownを使う
  5. モンキーパッチではなく、より型安全なアプローチを採用する
  6. 健全性の罠を回避する
  7. 型カバレッジを監視し、型安全性のリグレッションを防ぐ

ジェネリックと型レベルプログラミング

  1. ジェネリックを型に対する関数と考える
  2. 不必要な型パラメーターを避ける
  3. オーバーロードシグネチャより条件型を優先的に使用する
  4. 条件型のユニオンでの分配を制御する
  5. テンプレートリテラル型を使ってDSLや文字列間の関係をモデリングする
  6. 型のテストを書く
  7. 型の表示に配慮する
  8. 再帰的なジェネリック型は末尾再帰にする
  9. コード生成を複雑な型の代替手段として検討する

TypeScriptレシピ集

  1. never型を使って網羅性チェックを行う
  2. オブジェクトに対して反復処理する方法を知る
  3. Record型を使って値の同期を保つ
  4. レストパラメーターとタプル型を使って、可変長引数の関数をモデリングする
  5. never型のオプションプロパティを使って、排他的論理和をモデリングする
  6. 名前的型付けのためにブランドを使うことを検討する

型宣言と@types

  1. TypeScriptと@typesはdevDependenciesに追加する
  2. 型宣言の依存関係に関わる3つのバージョンを理解する
  3. パブリックなAPIで使われるすべての型をエクスポートする
  4. APIのコメントにTSDocを使う
  5. コールバックのthisがAPIの一部なら、それに型を与える
  6. 型を部分的にコピーして依存を断ち切る
  7. モジュールオーグメンテーションを使って型を改善する

コードを書いて実行する

  1. TypeScriptの独自機能の使用を避け、ECMAScriptの機能を使う
  2. ソースマップを使ってTypeScriptをデバッグする
  3. 実行時に型を再構築する方法を知る
  4. DOMの型階層を理解する
  5. ターゲットとする環境の正確なモデルを作る
  6. 型チェックとユニットテストの関係を理解する
  7. コンパイラーのパフォーマンスに注意を払う

コードのモダン化とTypeScriptへの移行

  1. モダンなJavaScriptを書く
  2. @ts-checkとJSDocを使ってTypeScriptを試す
  3. allowJsを使ってTypeScriptとJavaScriptを共存させる
  4. 依存関係グラフの下から上へモジュールごとに移行する
  5. noImplicitAnyを有効にするまで、移行が完了したと考えない

付録B 推奨事項の実践法

  1. コンパイラーオプションやリンターを使ってコードに規約を適用する

感想

コードを動かしながら読むために、最初は Deno を使うつもりだった。しかし、コンパイラオプションも設定できる TS Playground のほうが楽だった。なお、Node.js も v23.6.0 から、追加の設定なしで TypeScript を直接実行できるようになったらしい。

1 章ずつおすすめの項目を選んで、社内で共有したい。訳者の方の講演では、各章から「推し」(共感したもの、面白かったもの、勉強になったもの)を選んで紹介していた。それに倣って、自分の推しを章ごとに挙げておく。

講演の内容とは関係ないが、スライド上で型にカーソルを合わせると詳細が表示されるのに驚いた。Slidev を使うと、このように型を表示できるらしい。

関連