TypeScript Design Patterns
This guide rereads the GoF design patterns from one angle: what they look like when you write them in modern TypeScript.
About this guide
Most design patterns were organized around languages that put classes and inheritance at the center. TypeScript has first-class functions, discriminated unions, and structural subtyping, and there are places where you can reach the same goal without a class hierarchy.
So alongside explaining each pattern, every chapter judges whether that pattern is still needed in TypeScript. The judgment never stops at "language features can replace it" — it always lays out the conditions under which writing the pattern as a class still pays off.
This guide is written for readers who have written classes and interfaces in TypeScript and want more design options. The syntax itself is covered in the TypeScript Guide, and the norms for code quality in Clean Code Guide.
How each chapter is structured
Every pattern chapter uses the same five sections. That is a promise to keep facts and editorial judgment from mixing.
| Section | What goes in it |
|---|---|
| The problem this pattern set out to solve | The intent the pattern defined and the conditions it applies under, with sources |
| Writing it straightforwardly with classes | A TypeScript implementation that follows the pattern as written |
| Replacing it with language features | The language features you can reach for instead, with sources from specs and documentation |
| How this series judges it | This is the only editorial judgment. It lays out when language features suffice and when to keep writing a class |
| How this relates to existing articles | Links to existing articles that cover the same subject |
Each judgment is one of three: "language features can replace it," "conditional," or "a class implementation is recommended." A judgment is this guide's position rather than a fact, so it comes with its grounds and with what would overturn it.
Creational patterns
| Chapter | Pattern | What it covers |
|---|---|---|
| 01 | Singleton | How far the single instance an ES module gives you reaches, and where that stops |
| 02 | Factory Method and Abstract Factory | The conditions under which creation can move into a function |
| 03 | Builder | When a literal is enough, and when the type expresses staged requirements |
Structural patterns
| Chapter | Pattern | What it covers |
|---|---|---|
| 04 | Adapter | The boundary structural subtyping removes |
| 05 | Decorator | Why it is a different concept from TypeScript's Decorators syntax |
| 06 | Proxy | Why it is a different concept that happens to share a name with the built-in Proxy |
| 07 | Composite | Representing a tree with a recursive discriminated union |
Behavioral patterns
| Chapter | Pattern | What it covers |
|---|---|---|
| 08 | Strategy | How far passing a function alone gets you |
| 09 | Observer | How much EventTarget and AbortSignal cover |
| 10 | State | Forbidding invalid transitions in the type system |
| 11 | Template Method | Fixing the skeleton through inheritance versus injecting hook functions |
| 12 | Iterator | The iteration abstraction the language absorbed |
| 13 | Visitor | The role the exhaustiveness check takes over |
| 14 | Chain of Responsibility | The middleware shape, and passing context through types |
A pattern outside GoF, and the wrap-up
| Chapter | Contents |
|---|---|
| 15 | Repository. A pattern that comes from PoEAA rather than GoF, covered from the angle of expressing it in types |
| 16 | Short takes on the patterns that got no chapter, and the full list of judgments |
Patterns without a chapter of their own
Covering all 23 patterns at the same density would break the length, so this guide narrows to the ones with the most room for discussion from a TypeScript angle. The following eight get no chapter of their own and are covered briefly in the summary. This selection is this guide's editorial judgment.
| Pattern | Why it got no chapter of its own |
|---|---|
| Prototype | Its subject is the means of copying, and there is not enough to argue about to fill a chapter |
| Facade | It centers on narrowing what you expose, which leans into module design |
| Command | Representing operations as data overlaps with the Visitor chapter, and existing articles cover it in a different context |
| Bridge | Separating abstraction from implementation tends to overlap with Strategy and Adapter |
| Flyweight | Its subject is cutting memory through sharing, which leans into runtime behavior |
| Mediator | Placing a mediator raises few points specific to TypeScript |
| Memento | Saving and restoring state ends up reaching for the same tools as Prototype |
| Interpreter | Its subject is evaluating a syntax tree, which overlaps with what the Visitor chapter covers |