In TypeScript, decorators are a powerful feature that allow you to modify or enhance classes and their members (such as properties and methods) in a declarative way. This tutorial will focus on method decorators, which enable you to add functionality to class methods without altering the original implementation.
Decorators provide a clean and maintainable way to extend the behavior of your code, making them an essential tool for advanced TypeScript development. By the end of this section, you'll understand how to create and apply method decorators effectively.
A method decorator is a function that can be applied to a class method to modify its behavior or add additional functionality. Method decorators are called with three arguments:
Here is the basic syntax for a method decorator:
function myMethodDecorator(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
// Your implementation here
}
You can then apply this decorator to a class method using the `@` symbol:
```typescript
class MyClass {
@myMethodDecorator
myMethod() {
console.log('Hello from myMethod!');
}
}
## Examples
### Basic Method Decorator
Let's start with a simple example where we create a method decorator that logs when a method is called.
```typescript
function logMethod(target: any, 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(`\${propertyKey} returned`, result);
return result;
};
return descriptor;
}
class Calculator {
@logMethod
add(a: number, b: number): number {
return a + b;
}
}
const calculator = new Calculator();
calculator.add(2, 3);
Calling add with arguments [2, 3] add returned 5
In this example, the logMethod decorator logs the method name, its arguments, and its return value. The original method is preserved using originalMethod.apply(this, args).
Another common use case for method decorators is to measure the execution time of a method.
function timeMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args: any[]) {
const start = performance.now();
const result = originalMethod.apply(this, args);
const end = performance.now();
console.log(`\${propertyKey} took \${end - start} milliseconds`);
return result;
};
return descriptor;
}
class PerformanceTest {
@timeMethod
computeHeavyTask(): number {
let sum = 0;
for (let i = 0; i < 1000000; i++) {
sum += i;
}
return sum;
}
}
const test = new PerformanceTest();
test.computeHeavyTask();
computeHeavyTask took 12.345 milliseconds
This decorator uses the performance.now() API to measure and log the time taken by the method.
Decorators can also be used to implement access control mechanisms, such as restricting method calls based on certain conditions.
function restrictMethod(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function(...args: any[]) {
if (this.isLoggedIn) {
return originalMethod.apply(this, args);
} else {
console.log('Access denied');
}
};
return descriptor;
}
class User {
isLoggedIn = false;
@restrictMethod
sensitiveOperation() {
console.log('Sensitive operation performed');
}
}
const user = new User();
user.sensitiveOperation(); // Access denied
user.isLoggedIn = true;
user.sensitiveOperation(); // Sensitive operation performed
In this example, the restrictMethod decorator checks if the user is logged in before allowing the method to execute.
Now that you've learned about method decorators, the next step is to explore Property Decorators. Property decorators allow you to modify or enhance class properties in a similar way to method decorators. Understanding both types of decorators will give you a comprehensive toolkit for extending TypeScript classes effectively.
Stay tuned for more advanced topics and practical examples as we continue our journey through TypeScript's powerful features!