TypeScript Decorators

Olesya Miller
3 min readJun 1, 2021

Hi everyone! It’s Monday and that means it’s time for my weekly blog post!

So what are TypeScript decorators?

  • functions that can be used to modify different properties/methods in the class
  • not the same as JavaScript decorators
  • used inside/on classes only
  • understanding the order in which decorators are run is the key to understanding them
  • experimental

Let’s start with creating the bare bones of a JavaScript class (in order to understand the content of this article you should have a basic knowledge of OO programming)

class Boat {
color: string = 'red';
get formattedColor(): string {
return `This boats color is ${this.color}`
};
pilot(): void {
console.log("I love TypeScript decorators")
}
}

We just created an instance of a property, an accessor (which is a getter in our case) and we have a method. Now we can create a decorator and to apply it to every single one of those things inside out Boat class.

Let’s create our first decorator in the same file right underneath our class

function testDecorator(target: any, key: string):void {
console.log("Target:", target)
console.log("Key:", key)
}

We have the decorator ready and now need to apply it inside of our class. Let’s place it above our pilot() function like that

class Boat {
color: string = 'red';
get formattedColor(): string {
return `This boats color is ${this.color}`
};
@testDecorator
pilot(): void {
console.log("I love TypeScript decorators")
}
}
function testDecorator(target: any, key: string):void {
console.log("Target:", target)
console.log("Key:", key)
}

Now let’s run our file and see what happens

//console output
Target: Boat {formattedColor: [Getter], pilot: [Function]}
Key: pilot

Before talking about the above output let’s talk about how decorators on property/accessor/method actually work (inside our class we have written out one of each of those).

The decorator function itself is going to be called with a couple of different arguments:

  • prototype of the object
  • key of property/accessor/method that the decorator is being applied to
  • decorators are applied when when the code for this file is run (not when an instance is created)

In this case we are talking about the prototype of class Boat. Whenever we create a class it also created Boat constructor function and defines a prototype on the constructor function.

So the first argument to our testDecorator() function is prototype of the class Boat

function testDecorator(target: any, key: string):void {
console.log("Target:", target)
console.log("Key:", key)
}

That means that it is going to be an object with all the different function that we defined on class Boat. That’s why we see this in the console output

//console output
Target: Boat {formattedColor: [Getter], pilot: [Function]}

‘Target: Boat” is the prototype of Boat which is listing all the functions we defined on it — “{formattedColor: [Getter], pilot: [Function]}”. We will notice that our property definition does not exist inside the prototype object because it gets moved to the constructor function.

The second argument is the key of property/accessor/method that the decorator is being applied to. In our case we applied the decorator to the pilot() method. That’s what we see on the second line of the console output

//console output
Target: Boat {formattedColor: [Getter], pilot: [Function]}
Key: pilot

I have to stop right now guys, this is obviously not everything I have to tell you about decorators. I will continue next week!

Happy coding!

--

--