Decorators in TypeScript
Learn about Decorators in TypeScript with this detailed tutorial. Includes explanations and examples to help you master decorators.
Introduction
Decorators are a special kind of declaration that can be attached to a class, method, accessor, property, or parameter. Decorators are a stage 2 proposal for JavaScript and are available as an experimental feature in TypeScript. Decorators provide a way to add both annotations and a meta-programming syntax for class declarations and members.
Enabling Experimental Decorators
To use decorators in TypeScript, you need to enable the experimentalDecorators compiler option in your tsconfig.json
file.
{
"compilerOptions": {
"experimentalDecorators": true
}
}
Class Decorators
A class decorator is a function that takes a class constructor and returns a new constructor or modifies the existing one.
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}`;
}
}
Explanation
In this example, the sealed
decorator seals the constructor and its prototype, preventing new properties from being added.
Method Decorators
A method decorator is a function that takes three arguments: the target (either the constructor or prototype), the property key, and the property descriptor.
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}`;
}
}
Explanation
In this example, the enumerable
decorator sets the enumerable property of the greet
method to false
.
Accessor Decorators
An accessor decorator is similar to a method decorator but is applied to an accessor (getter or setter).
function configurable(value: boolean) {
return function(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
descriptor.configurable = value;
};
}
class Point {
private _x: number;
private _y: number;
constructor(x: number, y: number) {
this._x = x;
this._y = y;
}
@configurable(false)
get x() {
return this._x;
}
@configurable(false)
get y() {
return this._y;
}
}
Explanation
In this example, the configurable
decorator sets the configurable property of the x
and y
accessors to false
.
Property Decorators
A property decorator is a function that takes two arguments: the target (either the constructor or prototype) and the property key.
function format(formatString: string) {
return function(target: any, propertyKey: string) {
let value: string;
const getter = () => value;
const setter = (newValue: string) => {
value = `${formatString} ${newValue}`;
};
Object.defineProperty(target, propertyKey, {
get: getter,
set: setter,
enumerable: true,
configurable: true
});
};
}
class Greeter {
@format("Hello")
greeting: string;
constructor(message: string) {
this.greeting = message;
}
}
let greeter = new Greeter("world");
console.log(greeter.greeting); // Hello world
Explanation
In this example, the format
decorator formats the value of the greeting
property by prepending the format string to it.
Parameter Decorators
A parameter decorator is a function that takes three arguments: the target (either the constructor or prototype), the property key, and the parameter index.
function required(target: any, propertyKey: string, parameterIndex: number) {
console.log(`Parameter at index ${parameterIndex} in ${propertyKey} is required`);
}
class Greeter {
greet(@required message: string) {
return `Hello, ${message}`;
}
}
Explanation
In this example, the required
decorator logs the parameter index and property key of the decorated parameter.
Conclusion
Decorators in TypeScript provide a powerful way to add metadata and modify the behavior of classes, methods, accessors, properties, and parameters. By understanding and using decorators, you can write more expressive and maintainable code.