Skip to main content
Loading...

TypeScript 5.0

Inspiring technology by Hunters

Our technology trend Hunters are as relentless as ever. This new edition of Inspiring Technology is about decorators within TypeScript 5.0. Read on!

The TypeScript 5.0 release brought a new standard with the use of decorators. Decorators are a TypeScript feature allowing developers to modify the behaviour 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

Decorator is a structural design pattern that allows a new functionality to be added dynamically to a base object. This functionality is added by wrapping the base object in a wrapper object that provides the added behaviours.
 

For example, an interface in which a document is displayed under the decorator pattern could look like this:

patrón Decorator

And the decorator pattern can be used to add a functionality to display the document in different formats:

decorator

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 will explain later. A decorator can perform up to four functions, depending on the type of component on which it is applied:

  • Making changes to the entity to be decorated.
  • Replacing the entity to be decorated by another of the same type.
  • Displaying access to the entity to be decorated to third parties.
  • Processing the entity to be decorated and its container (if any), e.g. a class method and that class.

A decorator can also be applied to multiple components and can receive parameters, so it is possible to change its behaviour depending on the component on which it is used.

When can decorators be applied?

A example of how decorators can be used is to create logs when class methods are executed.

To do so, as shown in the below image, a pair of classes with methods are declared, and the tag “@log” is used to indicate that these methods should be decorated by applying the “log” decorator.

Typescript

The decorator log is then declared:

Typescript

This method uses the original method and a context object as parameters, which contain 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 instructions before and after the original method call is made.

Finally, we execute the functions annotated with “@log” as follows:

And we get the following result: 

Decorators can also be used to validate properties/fields data of a given class. However, since data initialisation (init/constructor) and assignment (set) are carried out separately, we would have to define a decorator for each of these functionalities. Our best allies when it comes to simplifying this type of implementation are auto-accessors.

But... what are auto-accessors?

Auto-accessors are a new feature of the TypeScript language added in version 4.9. They are similar to fields in a class, but differ in their implementation at execution time. Due to the execution time difference, it is possible to easily decorate both data initialisation and data allocation and retrieval.
 

See the following example, where we validate that the number provided is not less than 0:

To begin with, we define a class with a self-accessor instead of a traditional field. This is done by placing the word accessor before the field definition.

We use the tag “@minimumNumber0” for the auto-accessor to apply the decorator. Finally, we define the decorator as follows: 

As we can see here, the decorator receives the original initialisers, getters and setters from the auto-accessor, defines the function with which the field values will be validated and applies the function on the decorated initialisers and setters. As nothing is required in the getter, it simply returns the original call.

Now, when we try to provide “age” values to the auto-accessor, like so:

We get the following results:

Finally, the decorator can be parameterised to receive the minimum value instead of setting it to 0. This is achieved by implementing a Decorator Factory.

Decorator Factory

A Decorator Factory allows us to input parameters for a decorator to alter its behaviour.

To parameterise the decorator used in the previous example, it would be enough to wrap the decorator in a function that receives a parameter, as shown below:

We would also have to add the minimum value as a parameter to the label with which the decorator is called:

Conclusions

Decorators are tools that can help with code reuse and increase code clarity. They also allow us to implement functionalities other than those described above, such as dependency injection and entity access control, so they are tools with powerful and diverse capabilities.

However, depending on the tasks for which they are intended to be used, their implementation may be more complex, so they are not always the best option.
 

Whant to know more about Hunters?

A Hunter rises to the challenge of trying out new solutions, delivering results that make a difference. Join the Hunters programme and become part of a diverse group that generates and transfers knowledge.

Anticipate the digital solutions that will help us grow. Learn more about  Hunters.