StructuralTypeScriptverifiedVerified

Decorator Pattern in TypeScript

Attaches additional responsibilities to an object dynamically by wrapping it in decorator objects that share the same interface.

How to Implement the Decorator Pattern in TypeScript

1Step 1: Define the component interface and base implementation

interface Component {
  operation(): string;
}

class ConcreteComponent implements Component {
  operation(): string {
    return "ConcreteComponent";
  }
}

2Step 2: Create the base decorator and concrete decorators

class BaseDecorator implements Component {
  protected wrappee: Component;
  constructor(component: Component) {
    this.wrappee = component;
  }
  operation(): string {
    return this.wrappee.operation();
  }
}

class ConcreteDecoratorA extends BaseDecorator {
  operation(): string {
    return `DecoratorA(${super.operation()})`;
  }
}

class ConcreteDecoratorB extends BaseDecorator {
  operation(): string {
    return `DecoratorB(${super.operation()})`;
  }
}

3Step 3: Compose decorators and observe layered behavior

function clientCode(component: Component): void {
  console.log("Result:", component.operation());
}

const simple = new ConcreteComponent();
clientCode(simple);
// Result: ConcreteComponent

const decorated = new ConcreteDecoratorB(new ConcreteDecoratorA(simple));
clientCode(decorated);
// Result: DecoratorB(DecoratorA(ConcreteComponent))

Decorator Pattern Architecture

hourglass_empty

Rendering diagram...

lightbulb

Decorator Pattern in the Real World

Think of adding espresso shots and syrups to a coffee order. A plain coffee is the base component. Each addition—an espresso shot, vanilla syrup, oat milk—is a decorator that wraps the previous cup, adding its own cost and flavor. You can combine them in any order without the café needing a separate menu item for every combination.