BeCuriouzLearn something new every day
Decorators: Attaching Behavior with @
💡 A decorator is an @-tagged function that wraps a class or member to add reusable behavior — like logging or validation — without editing that code directly.
A decorator is a special function you attach to a class, method, or field using the @ syntax placed right above it. Think of it as a tag that wraps or modifies whatever it sits on — without you rewriting that thing's own code. If earlier cards showed you how a class bundles data and methods, a decorator lets you bolt extra behavior onto that bundle from the outside.
The classic example is a method decorator that adds logging. You write the timing/logging logic once inside the decorator, then reuse it by tagging any method with @log:
function log(originalMethod: any, _ctx: ClassMethodDecoratorContext) {
return function (this: any, ...args: any[]) {
console.log(`Calling ${String(_ctx.name)}`);
return originalMethod.call(this, ...args);
};
}
class Api {
@log
fetchUser(id: number) { return { id }; }
}Calling new Api().fetchUser(1) now logs Calling fetchUser before returning — the decorator replaced the method with a wrapped version. This is why decorators shine for cross-cutting concerns: logging, timing, caching, validation, and access control — behaviors that many methods share but don't belong inside any one of them.
Decorators became a Stage 3 TC39 standard and ship natively in TypeScript 5.0+ (no config flag needed for the modern form). You'll meet them constantly in frameworks like Angular (@Component, @Injectable) and NestJS (@Controller, @Get), where a single tag registers a class with the framework. For now, just recognize the shape: @something above a class or member means "wrap this with extra behavior."