โจ Understanding Method Decorators in TypeScript: A Beginner's Guide
๐ Introduction
If you're familiar with JavaScript and new to TypeScript, you might have heard about decorators. Decorators are a powerful feature that allows you to add metadata and modify the behavior of your classes and methods. In this guide, we'll focus on method decorators, explaining what they are and how to use them with practical examples. By the end, you'll see how decorators can simplify and enhance your code.
๐ What is a Method Decorator?
A method decorator is a special function that you can attach to a method in a class to modify its behavior. It's a way to add extra functionality or logic, such as logging method calls or measuring execution time.
๐จ Basic Syntax
In TypeScript, a method decorator is denoted by the @
symbol followed by the decorator name, placed above the method definition.
class ExampleClass {
@decorator // โฌ
๏ธ This is where we apply the decorator
method() {
// Method logic
}
}
๐ ๏ธ Example: Logging Method Calls
Let's create a simple method decorator that logs each time a method is called. This is a great way to understand the basics of how decorators work.
// ๐ฏ A method decorator to log method calls
function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
// Save the original method for later use
const originalMethod = descriptor.value;
// Modify the method descriptor to wrap the original method
descriptor.value = function (...args: any[]) {
console.log(`Calling ${propertyKey} with arguments:`, args); // ๐ Log the method name and arguments
return originalMethod.apply(this, args); // ๐ ๏ธ Call the original method
};
// Return the modified descriptor
return descriptor;
}
Explanation
target: The prototype of the class for instance methods, or the constructor for static methods.
propertyKey: The name of the method being decorated.
descriptor: An object that provides access to the method's metadata, allowing you to modify its behavior.
๐ Applying the Decorator
Now, let's apply this log
decorator to a method in a class.
class Car {
@log // โฌ
๏ธ Apply the log decorator to the drive method
drive(speed: number) {
console.log(`Driving at ${speed} km/h`);
}
}
const myCar = new Car();
myCar.drive(100);
// Logs: "Calling drive with arguments: [100]"
// Logs: "Driving at 100 km/h"
Breakdown
The
log
decorator is applied to thedrive
method.Each time the
drive
method is called, the decorator logs the method name and arguments before executing the original method.
๐ How Method Decorators Work
What the decorator does is wrap your custom logic around the original method. This means that when the method is called, the decorator can execute its custom logic before or after the original method runs. The original method remains unchanged and intact; the decorator simply adds extra behavior.
Think of it like wrapping a gift ๐. The gift (original method) is still the same, but you can add a nice wrapping (decorator) to make it more special or functional!
๐ Real-World Example:
Measuring Execution Time
Let's create another useful decorator that measures how long a method takes to execute.
// โฑ๏ธ A method decorator to measure execution time
function measureTime(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
// Save the original method for later use
const originalMethod = descriptor.value;
// Modify the method descriptor to wrap the original method
descriptor.value = function (...args: any[]) {
const start = performance.now(); // ๐ Start time
const result = originalMethod.apply(this, args); // ๐ ๏ธ Call the original method
const end = performance.now(); // ๐ End time
console.log(`${propertyKey} executed in ${(end - start).toFixed(2)} ms`); // ๐ Log the execution time
return result; // Return the result of the original method
};
// Return the modified descriptor
return descriptor;
}
Explanation
The
measureTime
decorator measures the time taken by the method to execute.performance.now
()
is used to get the current timestamp in milliseconds.
๐ Applying the Decorator
Let's apply the measureTime
decorator to a method.
class Rocket {
@measureTime // โฌ
๏ธ Apply the measureTime decorator to the launch method
launch(destination: string) {
console.log(`Launching to ${destination}`);
// Simulate some delay
for (let i = 0; i < 1e6; i++) {}
}
}
const myRocket = new Rocket();
myRocket.launch("Mars");
// Log: "Launching to Mars"
// Log: "launch executed in 1.42 ms"
Breakdown
The
measureTime
decorator is applied to thelaunch
method.It measures and logs the execution time of the
launch
method each time it's called.
๐ Conclusion
Method decorators in TypeScript provide a powerful way to enhance your methods with additional functionality. By understanding and using decorators, you can write cleaner, more maintainable code. Try creating your own decorators and see how they can simplify your development process.
Happy coding! โจ
Subscribe to my newsletter
Read articles from Jobin Mathew directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Jobin Mathew
Jobin Mathew
Hey there! I'm Jobin Mathew, a passionate software developer with a love for Node.js, AWS, SQL, and NoSQL databases. When I'm not working on exciting projects, you can find me exploring the latest in tech or sharing my coding adventures on my blog. Join me as I decode the world of software development, one line of code at a time!