
The release of TypeScript 5.0 includes a new standard for the use of Decorators. Decorators are a TypeScript feature that allows you to modify the behavior of classes and their members in a reusable way . They are based on the design pattern of the same name, which we explain in this article.
Discovering the Decorator design pattern
The Decorator design pattern is a structural design pattern that allows you to dynamically add functionality to a base object . This addition of functionality is accomplished by wrapping the base object in an encapsulating object that provides the added behaviors.
As an example of the Decorator pattern, you could consider an interface that displays a document like the following:

And you could use the Decorator pattern to add the functionality to present the document in different formats as follows:

Main features and uses
Decorators in TypeScript can be used on components such as properties/fields, getters, setters, class methods, classes, and auto-accessors, which we'll explain later. A decorator can perform up to four functions , depending on the type of component it's applied to:
- Make changes to the entity to be decorated.
- Replace the entity to be decorated with another of the same type.
- Expose access to the entity to be decorated to third parties.
- Process the entity to be decorated and its container (if it has one), for example, a class method and the class itself.
On the other hand, a Decorator can be applied to multiple components and can receive parameters , so it is possible to change its behavior depending on the component on which it is used.
Where can Decorators be applied?
A simple example of applying Decorators could be using them to log when class methods are executed.
To do this, as can be seen in the following image, a pair of classes with methods are declared, which are annotated with the “@log” tag to indicate that these methods must be decorated by applying the “log” decorator.

The log decorator is then declared:

This method takes as parameters the original method and a context object , which contains various data about the context in which the decorator method is executed (in this case, the name of the original method is used to display it). The method returns a function that executes statements before and after the call to the original method.
Finally, if we run the functions annotated with “@log” as follows:

We obtain the following result:

On the other hand, decorators could be used to validate data from a class's properties/fields. However, since data initialization (init/constructor) and assignment (set) are performed separately, it would be necessary to define a decorator for each of these functions . To simplify this type of implementation, auto-accessors will be our best allies.
But... what are auto-accessors?
Auto-accessors are a new feature of the TypeScript language , added in version 4.9. They are similar to class fields, but differ in their runtime implementation. Due to the difference in runtime, it is possible to easily decorate both data initialization and assignment and retrieval.
To illustrate this case, the following example is presented, where it is validated that the number provided is not less than 0:

To begin, a class is defined with an auto-accessor instead of a traditional field. To do this, the keyword accessor is used before the field definition.
The auto-accessor is annotated with the tag “ @minimumNumber0 ” to apply the decorator. Finally, the decorator is defined as follows:

As you can see, the decorator receives the original initializers, getters, and setters from the auto-accessor, defines the function with which the field values will be validated, and applies the function to the decorated initializers and setters. Since nothing is required in the getter, it simply returns the original callback.
If you now try to provide values to the “age” auto-accessor as follows:

The following results are obtained:

Finally, the decorator could be parameterized to receive the minimum value instead of setting it to 0. This would be achieved by implementing a Decorator Factory .
Decorator Factory
A Decorator Factor allows you to provide parameters to a Decorator to alter its behavior.
To parameterize the Decorator used in the previous example, it would be enough to wrap the decorator in a function that receives a parameter, as can be seen in the following image:

Additionally, it would be necessary to add the minimum value as a parameter to the tag with which the Decorator is called:

Conclusions
Decorators are tools that can help with code reuse and improve code clarity. They also allow for implementing features other than those described above, such as dependency injection and entity access control, so it can be seen that they are tools with powerful and diverse capabilities.
On the other hand, depending on the tasks for which they are intended to be used, the complexity of their implementation may increase , so in certain cases they may not be the best option.
Want to know more about Hunters?
Being a Hunter means accepting the challenge of testing new solutions that deliver differentiated results. Join the Hunters program and become part of a cross-functional group capable of generating and transferring knowledge.
Get ahead of the digital solutions that will drive our growth. Learn more about Hunters .