Adapter — The Boundary Structural Subtyping Removes
TypeScript uses structural subtyping, so anything whose shape matches can be passed straight through without an explicit implements. This chapter looks at where the need for a converter in between still remains.
Advanced functions
In this chapter, you learn more advanced features of functions in TypeScript.
Advanced type operations
In this chapter, you learn about TypeScript's advanced type operation features. Combining them lets you write more type-safe and expressive code.
Basic data types
In this chapter, you learn TypeScript's basic data types.
Builder — Staged Construction Expressed with Object Literals and Types
An object with many optional arguments can be assembled from a literal. An ordering constraint such as "you cannot build until this value is set" is something TypeScript's types can express.
Chain of Responsibility — The Middleware Shape
The structure of handing a request along step by step is widely used as middleware in Node.js. This chapter goes as far as building context up through types.
Class basics
In this chapter, you learn the basics of how to write classes in TypeScript.
Classes and interfaces
Designing classes and interfaces in TypeScript. Explains information hiding (encapsulation) / single responsibility / keeping classes small / preferring composition over inheritance with Bad / Good comparisons. Also covers the ideas of cohesion and coupling.
Clean Code Guide
A practical guide to writing clean, maintainable TypeScript. It explains step by step why each rule matters and how to apply it. A roadmap that organizes design principles for leveraging the type system across 13 articles.
Comments
The art of comments in TypeScript. The core principle that Why goes in comments and What goes in code, plus patterns to keep stale comments from contradicting the code during maintenance. Also covers using JSDoc and writing self-documenting code.
Composite — Recursive Discriminated Unions
When you handle a tree, a recursive discriminated union can stand in for a class hierarchy built on a shared interface. The subject here is a file system.
Comprehensive exercise project
In this chapter, you build a CLI task management tool using the knowledge you have learned so far.
Conditionals
Best practices for conditional branching in TypeScript. A guide to keeping nesting shallow with early returns, discriminated unions and exhaustiveness checks, and reducing if statements with polymorphism, explained with Bad / Good comparisons.
Conflicts and limits — deciding which one to take
The five principles pull against each other. Push splitting and a change touches more files; interpose an abstraction and it takes more steps to trace what actually runs. This chapter covers how to decide when they conflict, and modern criticism of SOLID itself.
Decorator — A Pattern Distinct from TC39 Decorators
Despite the shared name, GoF's Decorator pattern and TypeScript's Decorators syntax are different concepts. This chapter separates the two, then compares the pattern with composition through higher-order functions.
Defining functions
Best practices for designing functions in TypeScript. Compares single responsibility / pure functions / early return / minimizing arguments / avoiding side effects / the DRY principle with Bad / Good examples. Also covers clarifying input and output with type annotations.
Defining variables
Best practices for defining variables in TypeScript. Explains turning magic numbers / magic characters into constants, choosing between const and let, minimizing scope, and not giving a variable multiple meanings, using Bad / Good comparisons.
Design & Quality
A hub for the domain covering how code is written and structured. It spans everyday decisions such as naming and splitting functions, a closer look at the SOLID principles, a rereading of the GoF patterns in modern TypeScript, and what changes when the test comes first.
Design patterns — four archetypes and their vocabulary
This chapter presents Strategy, Singleton, Observer, and Abstract Factory from the problems each was designed to solve. It covers commonly conflated pairs like Strategy vs. State, Observer vs. polling, and Abstract Factory vs. Factory Method.
Development toolchain
In this chapter, you learn about the development tools used in a TypeScript project.
Express + best practices
In this chapter, you learn type-safe backend development that combines Express and TypeScript.
Factory Method and Abstract Factory — Moving Creation into Functions
In TypeScript, pulling creation logic out usually needs nothing more than a plain function and a union of literal types. Abstract Factory only earns its place when a constraint ties several related products together.
Function basics
In this chapter, you learn the basics of writing functions in TypeScript.
Generic constraints
In this chapter, you learn how to add constraints to generics, plus generic classes and interfaces.
Generics basics
In this chapter, you learn about generics, one of TypeScript's signature features.
Inheritance and interfaces
In this chapter, you learn about class inheritance and interfaces in TypeScript.
Iterator — The Pattern the Language Absorbed
The abstraction of iteration is in the language specification as Symbol.iterator and generators. This chapter checks whether any reason remains to write an Iterator class of your own.
Loops
How to choose between forEach / map / filter / reduce and the difference between for...of and for...in. Explains array-processing best practices that make intent clear with higher-order functions, using Bad / Good comparisons.
Mapped Types and Conditional Types
In this chapter, you learn about TypeScript's advanced type features, Mapped Types and Conditional Types. Once you understand them, you can create your own utility types.
Modules and tsconfig
In this chapter, you learn about TypeScript's module system and project configuration.
Naming conventions 1: case conventions, variables, and constants
Naming conventions in TypeScript, Part 1. Explains how to choose among the four case conventions (kebab, snake, Pascal, camel) and how to name variables, booleans, and constants, using Bad / Good comparisons. The gateway to naming well, so the code itself becomes documentation.
Naming conventions 2: functions and classes
Naming conventions in TypeScript, Part 2. Explains naming functions with verb patterns such as get / set / calculate, functions that return a boolean, suffix patterns for class names, and the criteria for not making method names redundant, using Bad / Good comparisons.
Naming conventions 3: improving naming quality
Naming conventions in TypeScript, Part 3. Covers principles that improve naming quality, such as pronounceable names, plural forms for arrays, unifying synonyms, contrasting words, avoiding meaningless words, and criteria for abbreviation, plus a comprehensive exercise and a quick reference summary.
Object types and type aliases
In this chapter, you learn how to define object types and how to create reusable types with type aliases (type).
Observer — The Mechanism the Platform Already Has
Before you build a notification mechanism of your own, there are standard tools: EventTarget and AbortSignal. This chapter looks at how far the standard gets you, unsubscription included.
Programming Languages
A hub for the domain covering language specifications themselves, JavaScript and TypeScript. It spans the foundation of variables, functions, and objects through to the type system and generics.
Proxy — A Different Concept That Shares a Name with the Built-in Proxy
JavaScript has a built-in object called Proxy, and it is not the same thing as GoF's Proxy pattern. This chapter covers both, using lazy loading and access logging as its subjects.
React + TypeScript
In this chapter, you learn type-safe frontend development that combines React and TypeScript.
Repository — A Pattern Outside GoF That Comes Up Often in Practice
Repository comes from PoEAA, not GoF. To avoid overlapping with the existing articles, this chapter narrows to how TypeScript's types express this boundary.
Schema validation with Zod
Define schemas with Zod and learn type inference, React Hook Form integration, and runtime validation of API responses.
Singleton — How Far a Module's Single Instance Reaches
An ES module is evaluated only once as long as it resolves to the same URL, so you get a single instance without writing a Singleton class. This chapter maps how far that guarantee reaches and when you still need another approach.
SOLID is not a single theory — where the five principles came from
The five SOLID principles were not born at the same time. Read the original text Martin published in 2000 and what you find are four principles of class design and six of package design, with SRP not among them. This chapter covers what the acronym hid.
SOLID principles
Explains the five SOLID principles of object-oriented design (single responsibility / open-closed / Liskov substitution / interface segregation / dependency inversion) with TypeScript examples. An introductory guide that contrasts each principle with Bad / Good code.
SOLID Principles in Depth
A seven-chapter series that digs into the five SOLID principles across three layers, why you follow them, when it's OK to break them, and how they get misused. Each chapter goes to the original text of the principle and covers how it is reassessed today.
Special types
In this chapter, you learn about TypeScript's special types.
State — Killing Invalid Transitions with Types
Instead of a class per state, representing states with a discriminated union lets the type forbid operations the current state cannot accept. The subject here is a vending machine.
Strategy — Functions Being First-Class
If all you do is swap behavior, passing a function is enough. What still makes you want to bundle things into an object is a strategy that carries several methods or state.
Summary
A recap of all 11 articles in the Clean Code Guide (TypeScript). It visualizes the big picture of naming, functions, type safety, object orientation, and the SOLID principles as a mindmap, and serves as a checklist to use while coding.
Summary — The Patterns Without a Chapter, and the Full List of Judgments
A short take on the eight patterns that got no chapter of their own, plus every judgment in the series collected into one table. It also lays out the steps for deciding whether to use a pattern.
Template Method — Inheritance and Injecting Hooks
Inheriting from an abstract class is not the only way to fix the skeleton of a procedure and swap out one part of it. This chapter sorts out how that differs from taking hook functions.
The dependency inversion principle — who owns the abstraction
DIP, DI, and IoC are separate concepts. Passing dependencies in from outside does not by itself invert anything. This chapter confirms from the original text what actually inverts, and which module the abstraction should belong to.
The interface segregation principle — half the motivation depends on the language
ISP has two motivations, avoiding recompilation and a design concern, and the former does not exist in TypeScript in its original form. In a structural type system you can satisfy ISP without carving out an interface.
The Liskov substitution principle — the types pass, the contract does not hold
LSP says a derived type must be substitutable for its base type, but the criterion for deciding substitutability lies in the contract. This chapter covers the four items the original text set out, precondition, postcondition, invariant, and history property, and how far the type checker is actually looking.
The open–closed principle — the cost when the prediction is wrong
OCP asks you to prepare extension points in advance, but misread the direction of extension and you are left with a wrong abstraction. This chapter confirms what the original text named as the means of achieving it, and covers how to judge its conflict with YAGNI.
The single responsibility principle — who "a reason to change" refers to
SRP's definition of "one reason to change" is subjective, and the granularity of the split shifts with every reader. This chapter covers what Martin meant when he later stated that this principle is about people, and what you lose when you split too far.
Type narrowing
In this chapter, you learn about "type narrowing," which is at the core of TypeScript's type system.
TypeScript Design Patterns
A 16-chapter guide that rereads the 23 GoF patterns in modern TypeScript. Each chapter judges whether language features can replace the pattern, and lays out the conditions under which writing it as a class still pays off.
TypeScript Guide
A 21-chapter guide that teaches TypeScript systematically, from the language spec to real-world practice. It progressively covers getting started, basic types, functions, classes and OOP, the advanced type system, generics, the development environment, and practical projects.
TypeScript-specific best practices
Best practices for using the TypeScript type system effectively. Explains avoiding any, choosing between unknown and never, generics, utility types, and narrowing with type guards, using Bad / Good comparisons.
Union types, literal types, and enums
In this chapter, you learn about union types that combine multiple types, literal types that allow only specific values, and enums that group related constants.
Utility types
In this chapter, you learn about the utility types built into TypeScript.
Visitor — The Exhaustiveness Check Stands In for It
With an exhaustiveness check built from a discriminated union and never, the type prevents forgotten cases without assembling Visitor's class hierarchy. The subject here is a syntax tree.
What is TypeScript? Setup
In this chapter, you learn the basic concepts of TypeScript and how to set up a development environment.
Your first program and type errors
In this chapter, you create your first TypeScript program and experience compiling and running it.