Typescript is a superset of Javascript. Typescript allows Javascript developers to add static type-checking and other modern features to plain Javascript. Some of these extra features do get added to the standard Javascript(ECMAScript).
The concept of Decorators is one of those extra features. In this article, we would see what Decorators are and how they can be used in Typescript.
What are Decorators?
Decorators are a feature in TypeScript that allow you to modify the behavior of classes, methods, properties, and other members at design time. Decorators are implemented as functions that can be attached to declarations using the @
symbol.
What are Decorators used for?
They can be used for a wide range of tasks, such as:
- Adding additional behavior to a class or its members.
- Implementing dependency injection.
- Modifying third-party libraries without having to change the implementation of the library itself.
Getting started
To use decorators, you have to set the experimentalDecorators
compiler to true
option in the tsconfig.json
file.
{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true,
}
}
After setting up your project to use decorators, let's get coding!
Types of Decorators
Class Decorators
Class decorators are used to modify the behavior of a class at design time. They can be applied to the class declaration itself, and can also be used to modify the constructor function of the class.
Here is an example of a class decorator that adds a new method to a class:
function addMethod(target: any) {
target.prototype.greet = function() {
console.log("Hello, world!");
};
}
@addMethod
class Greeter {
name: string;
constructor(name: string) {
this.name = name;
}
}
const greeter = new Greeter("Alice");
greeter.greet(); // logs "Hello, world!"
In this example, we define a class decorator called addMethod
that takes one argument, the target object (which is the constructor function of the class). The decorator adds a new method called greet
to the prototype of the target object.
We then apply the addMethod
decorator to the Greeter
class using the @
symbol. When we create a new instance of Greeter
and call the greet
method, the decorator intercepts the call and executes the new method that we added to the class.
Property Decorators
Property decorators are used to modify the behavior of a class property at design time. They can be applied to the property declaration itself, and can also be used to modify the descriptor object that describes the property's properties.
The property decorator receives two arguments.
- The prototype of the class for an instance member OR the constructor function of the class for a static member.
- The name of the property.
Here's an example of a property decorator:
function readonly(target: any, propertyKey: string) {
Object.defineProperty(target, propertyKey, { writable: false });
}
class MyClass {
@readonly
myProperty: string;
}
const myObject = new MyClass();
myObject.myProperty = "new value"; // throws a TypeError
In this example, we define a property decorator called readonly
that sets the writable
property of the target property descriptor to false
. We then apply the decorator to the myProperty
property of the MyClass
class using the @
symbol. Also Property decorators can be used to override the property being decorated. This can be done with the static method Object.defineProperty
.
Decorators are just a clean syntax for wrapping a piece of code with a function
Are there any downsides?
While decorators are a powerful tool for adding functionality to classes, properties, and methods in TypeScript, there are some downsides to consider:
Increased Complexity: Decorators can make the code more complex, especially if decorators are heavily used or if there are many decorators applied to a single property or method. This can make it harder to understand the behavior of the code, especially for developers who are not familiar with the decorator syntax.
Debugging: Debugging code that uses decorators can be more difficult because the decorator code is executed at runtime, which can make it harder to trace the flow of execution and find errors.
Limited Browser Support: While TypeScript supports decorators, they are not natively supported by all browsers. If you are targeting a browser that does not support decorators, you will need to use a transpiler like Babel to convert the decorator syntax to code that is compatible with that browser.
Performance: Using decorators can impact the performance of the application, especially if many decorators are used. The extra overhead of decorator code can slow down the execution of the application, especially on slower devices or when dealing with large amounts of data.
It's important to consider these downsides when deciding whether to use decorators in your TypeScript code. While decorators can be a useful tool for adding functionality to your code, they should be used judiciously and only when the benefits outweigh the costs.
Conclusion
At this point I hope you had a good understanding of decorators, how they work and when to use them or avoid using them. In this article I covered only two types of decorators, however, there’s much more to learn. Decorators in Typescript can be applied not only to classes and methods, but also to properties of classes, and method arguments. I hope that with your newly acquired understanding of decorators you’ll be able to pick it up easily from the documentation.
If you’ve enjoyed this article feel free to clap for it so more people will find it and enjoy it as well, and if you wish to see more of the stuff I write you’re welcome to follow me. Let me know in the comments if you have any questions.
Thanks for reading!
Latest comments (1)
Thanks, so easy actually, but as we add methods to the prototype does this mean that children classes get affected?