Introduction to Decorators
In this page:
What Is a Decorator?
A decorator is a function applied with the @ syntax directly above a class, method, property, or parameter; it receives information about the declaration it's attached to and can observe or modify it.
Example: What Is a Decorator?
function logged(target: any, context: ClassMethodDecoratorContext) {
console.log(`Decorator applied to ${String(context.name)}`);
}
class Greeter {
@logged
greet() {
return "hi";
}
}
new Greeter().greet();
Decorator Syntax
Decorators are written immediately before the declaration they decorate, and multiple decorators can be stacked on the same declaration, applying in a specific, well-defined order.
Example: Decorator Syntax
function first(target: any, ctx: ClassMethodDecoratorContext) {
console.log("first decorator on", String(ctx.name));
}
function second(target: any, ctx: ClassMethodDecoratorContext) {
console.log("second decorator on", String(ctx.name));
}
class Example {
@first
@second
run() {}
}
new Example().run();
Decorator Context
Standard decorators receive a context object describing what is being decorated — its kind, name, and other metadata — which the decorator can use to decide how to behave.
Example: Decorator Context
function describe(target: any, context: ClassMethodDecoratorContext) {
console.log("Decorating", context.kind, String(context.name));
}
class Service {
@describe
start() {}
}
new Service();
Replacing Decorated Values
Some decorators can return a compatible replacement value; method decorators, for example, commonly return a wrapped version of the original method that adds behavior like logging around the call.
Example: Replacing Decorated Values
function logCall(target: any, context: ClassMethodDecoratorContext) {
return function (this: any, ...args: any[]) {
console.log("Calling", String(context.name));
return target.call(this, ...args);
};
}
class Calculator {
@logCall
add(a: number, b: number) {
return a + b;
}
}
console.log(new Calculator().add(2, 3));
Enabling Modern Decorators
In current TypeScript, standard decorators work without needing the legacy experimentalDecorators compiler flag, following the newer, TC39-aligned decorators proposal instead of the older, non-standard implementation.
Example: Enabling Modern Decorators
// Modern (TC39) decorators work without experimentalDecorators:
function marker(target: any, context: ClassMethodDecoratorContext) {}
class Widget {
@marker
render() {
return "rendered";
}
}
console.log(new Widget().render());
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: