What It Is
The Chain of Responsibility pattern passes a request along a chain of handlers. Each handler either deals with the request or hands it to the next one. The sender only knows the first link — never who will actually solve it.
Example: A Support Line
A problem enters at the chat bot. What the bot cannot fix goes to tech support; what tech support cannot fix goes to the manager, who handles everything that arrives.
The next link is typed Handler | undefined, so the last link simply has none. this.next?.handle(problem) calls it only when it is there.
Pass it on until someone can
no internet travels one step and stops at tech support; the refund request travels the whole chain to the manager. The caller wrote the same one line both times.
Output: TypeScript file and captured output
class Handler {
private name: string
private canFix: (problem: string) => boolean
private next: Handler | undefined
constructor(name: string, canFix: (problem: string) => boolean,
next?: Handler) {
this.name = name
this.canFix = canFix
this.next = next
}
handle(problem: string): void {
if (this.canFix(problem)) {
console.log(this.name, "solved:", problem)
return
}
console.log(this.name, "passes it on")
this.next?.handle(problem)
}
}
const manager = new Handler("manager", () => true)
const tech = new Handler("tech support", (p) => p === "no internet", manager)
const bot = new Handler("chat bot", (p) => p === "forgot password", tech)
bot.handle("no internet")
console.log("---")
bot.handle("refund request")
When to Use It
Use it when several parties might handle a request and the right one is not known in advance — support escalation, middleware, event handling, approval workflows.
Skip it when the handler is always known — call it directly. A chain with one link, or one that always ends at the same link, is a plain function call in costume.
Pros and Cons
Pros: sender and receivers are decoupled; links can be added, removed and reordered freely; each handler stays small.
Cons: no guarantee anyone handles the request — a broken chain swallows it silently; following a request through many links makes debugging slower.