メインコンテンツまでスキップ

TypeScript デザインパターン

GoF のデザインパターンを、現代の TypeScript で書くならどうなるかという観点で読み直すガイドです。

このガイドについて

デザインパターンの多くは、クラスと継承を中心に据えた言語を前提に整理されました。TypeScript には第一級関数、判別可能ユニオン、構造的部分型があり、同じ目的をクラス階層なしで達成できる場面があります。

そこで本ガイドは、パターンの解説に加えて そのパターンが TypeScript でも必要かどうか を各章で判定します。判定は「言語機能で代替できる」で終わらせず、クラスとして書き続ける価値が残る条件も必ず並べて示します。

対象読者は、TypeScript でクラスとインターフェースを書いた経験があり、設計の選択肢を増やしたい人です。文法そのものは TypeScript ガイド、コード品質の規範は クリーンコードガイド で扱っています。

各章の構成

すべてのパターン章を同じ 5 つの節で構成します。事実と編集判断を混ぜないための約束です。

書くこと
このパターンが解こうとした問題そのパターンが定めた意図と適用条件。出典を示します
クラスで素直に書くパターンどおりの TypeScript 実装
言語機能で置き換える代わりに使える言語機能。仕様やドキュメントの出典を示します
本連載の判断ここだけが編集判断です。 言語機能で足りる条件と、クラスのまま書く条件を並べます
既存記事との関係同じ題材を扱った既存記事へのリンク

判定は「言語機能で代替できる」「条件付き」「クラス実装を推奨」の 3 つのいずれかで示します。判定は事実ではなく本ガイドの立場なので、根拠と、その判定が覆る条件をあわせて書きます。

生成に関するパターン

パターン扱うこと
01SingletonES モジュールが単一インスタンスを与える範囲と、その境目
02Factory Method と Abstract Factory生成を関数に寄せられる条件
03Builderリテラルで足りる場合と、型で段階的な必須を表す場合

構造に関するパターン

パターン扱うこと
04Adapter構造的部分型が消す境界
05DecoratorTypeScript の Decorators 構文とは別概念であること
06Proxy組み込みの Proxy と同じ名前の別概念であること
07Composite再帰的な判別可能ユニオンで木を表す

振る舞いに関するパターン

パターン扱うこと
08Strategy関数を渡すだけで足りる範囲
09ObserverEventTarget と AbortSignal でどこまで足りるか
10State不正な遷移を型で禁止する
11Template Method継承による骨組み固定とフック関数の注入
12Iterator言語仕様に取り込まれた反復の抽象化
13Visitor網羅チェックが引き取る役割
14Chain of Responsibilityミドルウェアという形と、型による文脈の受け渡し

GoF の外にあるパターンと総括

内容
15Repository。GoF ではなく PoEAA に由来するパターンを、型で表現する側面から扱います
16章を立てなかったパターンの短評と、判定の一覧

独立した章を設けなかったパターン

23 パターンをすべて同じ密度で扱うと分量が破綻するため、TypeScript の観点で議論の余地が大きいものに絞りました。次の 8 つは独立した章を設けず、まとめで短く扱います。この取捨は本ガイドの編集判断です。

パターン章を設けなかった理由
Prototype複製の手段が主題で、章 1 本に広げるだけの論点がないためです
Facade公開する範囲を絞る話が中心で、モジュール設計の話題に寄るためです
Commandデータとして表す形が Visitor の章と重なり、既存記事も別の文脈で扱っているためです
Bridge抽象と実装を分ける説明が Strategy や Adapter と重なりやすいためです
Flyweight共有によるメモリ削減が主題で、実行環境の挙動の話に寄るためです
Mediator仲介役を置くという構造そのものに TypeScript 固有の論点が出にくいためです
Memento状態の保存と復元が主題で、Prototype と同じ道具に行き着くためです
Interpreter構文木の評価が主題で、Visitor の章で扱う内容と重なるためです