Decorators are a powerful feature in TypeScript that allow you to modify classes, methods, properties, and parameters at runtime. They provide a way to add additional functionality to your code without having to modify the original source code. In this article, we will explore how to use decorators in Node.js TypeScript.
What are Decorators?
Decorators are a language feature in TypeScript that allow you to add metadata to classes, methods, properties, and parameters. They are denoted by the @ symbol followed by the decorator name. Decorators can be used to add functionality to your code at runtime, such as logging, caching, validation, and more.
Decorators work by wrapping the original function or class with another function that adds additional behavior. This is known as the decorator function. The decorator function takes the original function or class as a parameter, and returns a new function or class with the additional behavior.
Using Decorators in TypeScript
To use decorators in TypeScript, you must first enable the experimentalDecorators compiler option in your tsconfig.json file. This option tells the TypeScript compiler to recognize and support decorators.
{
"compilerOptions": {
"experimentalDecorators": true
}
}
Once you have enabled the experimentalDecorators option, you can use decorators in your code. Let's take a look at some examples.
Class Decorators
Class decorators are used to modify or add functionality to a class. They are applied to the class declaration, and the decorator function takes the class constructor as a parameter. Here is an example of a simple class decorator:
function logClass(constructor: Function) {
console.log(`Class ${constructor.name} was instantiated`);
}
@logClass
class MyClass {
constructor() {
console.log("Creating an instance of MyClass");
}
}
In this example, the logClass decorator function is applied to the MyClass class. When the MyClass constructor is called, the decorator function logs a message to the console.
Method Decorators
Method decorators are used to modify or add functionality to a class method. They are applied to the method declaration, and the decorator function takes three parameters: the target object, the method name, and the method descriptor. Here is an example of a simple method decorator:
function logMethod(target: Object, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args: any[]) {
console.log(`Calling ${propertyKey} with arguments: ${args}`);
const result = originalMethod.apply(this, args);
console.log(`Result of ${propertyKey}: ${result}`);
return result;
};
return descriptor;
}
class MyClass {
@logMethod
myMethod(arg1: string, arg2: number): string {
return `${arg1} ${arg2}`;
}
}
In this example, the logMethod decorator function is applied to the myMethod method of the MyClass class. When the myMethod method is called, the decorator function logs the method name and arguments to the console, calls the original method, logs the result, and returns the result.
Property Decorators
Property decorators are used to modify or add functionality to a class property. They are applied to the property declaration, and the decorator function takes two parameters: the target object and the property name. Here is an example of a simple property decorator:
function logProperty(target: Object, propertyKey: string) {
let value = target[propertyKey];
const getter = function() {
console.log(`Getting ${propertyKey}: ${value}`);
return value;
};
const setter = function(newValue: any) {
console.log(`Setting ${propertyKey}: ${newValue}`);
value = newValue;
};
Object.defineProperty(target, propertyKey, {
get: getter,
set: setter,
enumerable: true,
configurable: true,
});
}
class MyClass {
@logProperty
myProperty: string;
}
const myObject = new MyClass();
myObject.myProperty = "Hello";
console.log(myObject.myProperty);
In this example, the logProperty decorator function is applied to the myProperty property of the MyClass class. When the myProperty property is accessed or modified, the decorator function logs a message to the console.
Parameter Decorators
Parameter decorators are used to modify or add functionality to a class method parameter. They are applied to the parameter declaration, and the decorator function takes three parameters: the target object, the method name, and the parameter index. Here is an example of a simple parameter decorator:
function logParameter(target: Object, propertyKey: string, parameterIndex: number) {
console.log(`Method ${propertyKey} parameter ${parameterIndex} was called`);
}
class MyClass {
myMethod(@logParameter arg1: string, @logParameter arg2: number) {}
}
const myObject = new MyClass();
myObject.myMethod("Hello", 42);
In this example, the logParameter decorator function is applied to the arg1 and arg2 parameters of the myMethod method of the MyClass class. When the myMethod method is called, the decorator function logs a message to the console for each parameter.
Conclusion
Decorators are a powerful feature in TypeScript that allow you to modify or add functionality to classes, methods, properties, and parameters. They provide a way to add additional behavior to your code without having to modify the original source code. In this article, we have explored how to use decorators in Node.js TypeScript, including class decorators, method decorators, property decorators, and parameter decorators. With these tools at your disposal, you can write more flexible and extensible code in TypeScript.