TypeScript Decorators
Decorators provide a way to add both annotations and a meta-programming syntax for class declarations and members. They are a stage 3 proposal for JavaScript and are available as an experimental feature in TypeScript.
1. Configuration
To use decorators, you must enable the experimentalDecorators compiler option in your tsconfig.json:
{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true
}
}
2. What is a Decorator?
A Decorator is a special kind of declaration that can be attached to a class declaration, method, accessor, property, or parameter. Decorators use the form @expression, where expression must evaluate to a function that will be called at runtime with information about the decorated declaration.
3. Class Decorators
A Class Decorator is declared just before a class declaration. It is applied to the constructor of the class and can be used to observe, modify, or replace a class definition.
function Sealed(constructor: Function) {
Object.seal(constructor);
Object.seal(constructor.prototype);
}
@Sealed
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
greet() {
return "Hello, " + this.greeting;
}
}
4. Method Decorators
A Method Decorator is declared just before a method declaration. It can be used to observe, modify, or replace a method definition.
The decorator function receives three arguments:
- The constructor function (for static members) or the prototype (for instance members).
- The name of the member.
- The Property Descriptor for the member.
function Enumerable(value: boolean) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.enumerable = value;
};
}
class Greeter {
greeting: string;
constructor(message: string) {
this.greeting = message;
}
@Enumerable(false)
greet() {
return "Hello, " + this.greeting;
}
}
5. Decorator Factories
If you want to customize how a decorator is applied to a declaration, you can write a decorator factory. A decorator factory is simply a function that returns the expression that will be called by the decorator at runtime.
function Log(prefix: string) {
return function(target: any) {
console.log(`${prefix}: Class initialized`);
}
}
@Log("INFO")
class Person {
constructor(public name: string) {}
}
// Output: INFO: Class initialized