Create and Test Decorators in JavaScript

Netanel Basal
Netanel Basal
Published in
4 min readOct 2, 2017

--

I remember the first time I saw this sexy symbol. Yes, you know what I’m talking about. The at sign (@), above or before class, property or a method — a Decorator.

Decorators are a mechanism for observing, modifying, or replacing classes, methods or properties in a declarative fashion.

Decorators are a proposed standard in ECMAScript2016. In Typescript, we can enable them by setting the “experimentalDecorators” compiler flag, or with babel by installing the babel-plugin-transform-decorators plugin.

Creating decorators is actually quite easy. Let’s explore the various decorators.

Class Decorators

A Class decorator is a function that takes the constructor of the class as the only parameter. If the class decorator returns a value, it will replace the class declaration with the provided constructor function, i.e., override the constructor.

Let’s see an example of how to override the constructor.

We are returning a brand new Class that extends the original constructor function, in our case, the HelloComponent.

Let’s see an example of how to decorate the existing constructor. Let’s say we work with React and we want to know when React calls the render method.

We start by saving a reference to the original method, create a new one, call what we need and return the original method, letting React do its magic.

You can find a real-life example in this repository.

Method Decorators

A Method decorator is a function that takes three parameters.

The target:

Either the constructor function of the class for a static member, or the prototype of the class for an instance member.

The key:

The method name.

The descriptor:

The Property Descriptor for the method.

Let’s see an example of how to decorate an existing method with the setTimeout API. But before we can proceed, if you remember, the setTimeout function takes a number of milliseconds to wait before executing the code, so we need to learn how to pass options to a decorator by using a Decorator Factory.

A Decorator Factory is simply a function that returns the expression that will be called by the decorator at runtime.

Or in plain English, function that returns function.

We can get a reference to the original method from the descriptor value property.
Then, we will override the original value and create a new function that wraps the original with setTimeout.

Remember that you can also use a method decorator with static methods, for example:

The only difference in this case is you will get the constructor function of the class and not the prototype of the class.

You can find a real-life examples in this repository.

Property Decorators

A Property Decorator is declared just before a property declaration. Same as the others, it’s a function that takes two parameters.

The target:

Either the constructor function of the class for a static member, or the prototype of the class for an instance member.

The key:

The property name.

Let’s see an example of how to decorate a property.

The logProperty decorator above redefines the decorated property on the object. We can define a new property to the constructor’s prototype by using the Object.defineProperty() method. Here, we’re using get to return the value and log it. Secondly, we’re using set to directly write a value to the internal property and log it.

We can also use the new Reflect API instead of the defineProperty() method.

Now we can use our decorator like this:

You can find a real-life example in this repository.

Parameter Decorators

I’m going to skip this explanation because it’s the least common and it usually comes in conjunction with a method decorator. You can find a detailed example in the official documentation.

Composing Decorators

When multiple decorators apply to a single declaration, their evaluation is similar to function composition in mathematics. For example, the following code:

is equivalent to decoratorTwo(decoratorOne(someMethod)).

Testing Decorators

I’m going to use jest for testing, but you can use whatever test library you like. We have two ways to test decorators.

  1. Use them in your tests like in your code.

2. Since decorators are just functions we can test them like any other function.

Let’s close the article by testing the @timeout decorator.

We are passing the necessary parameters manually to the timeout decorator and leveraging the useFakeTimers feature from jest to check if our setTimeout function was called.

Wrapping Up

You can leverage decorators in your apps and create powerful things with them. Decorators are not only for frameworks or libraries, they are worth the time to learn as they can make your code more extensible and even more readable. Decorators also promote code reuse. Give them a try sometime soon 🙏

Follow me on Medium or Twitter to read more about Angular, Akita and JS!

👂🏻 Last but Not Least, Have you Heard of Akita?

Akita is a state management pattern that we’ve developed here in Datorama. It’s been successfully used in a big data production environment for over seven months, and we’re continually adding features to it.

Akita encourages simplicity. It saves you the hassle of creating boilerplate code and offers powerful tools with a moderate learning curve, suitable for both experienced and inexperienced developers alike.

I highly recommend checking it out.

Wrapping Up

You can leverage decorators in your apps and create powerful things with them. Decorators are not only for frameworks or libraries, they are worth the time to learn as they can make your code more extensible and even more readable. Decorators also promote code reuse. Give them a try sometime soon 🙏

Follow me on Medium or Twitter to read more about Angular, Vue and JS!

--

--

A FrontEnd Tech Lead, blogger, and open source maintainer. The founder of ngneat, husband and father.