TypeScript Decorators: Part 2

Olesya Miller
3 min readJun 7, 2021

Hi everyone! I hope you had a great weekend. Today I’m going to continue to write about TypeScript decorators. Last week I left off on creating a decorator called test Decorator() and explaining the code output in the console. This is what we have so far:

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)
}

This is the output

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

A quick recap of what’s going on there:

‘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.

Right now we have only two arguments on our decorator. There is actually a third argument on our decorator function that we can use. This third argument would be an object called ‘property descriptor’. I will deep dive on it a little later.

The most important thing to remember about TypeScript decorators — decorators are applied when the code for a class is run (not when an instance is created).

If you look at the code above again. At no point in time we made an instance of the Boat class. Nonetheless or decorator definitely ran when we ran the file itself.

Decorators, at the end of the day, are a way simpler than you would imagine. I’m going to prove it by coping the code we have above and placing it into a TypeScript playground tool — typescriptlang.org

On the right side we see the code that we get. Notice that as soon as we use a decorator on the left-hand side, in our output we get an added function definition called __decorate. That function gets automatically added to our code by TypeScript. If I remove the decorator on the left side the function on the right side goes away. So that function only exists to implement our decorator stuff

Now let’s bring the function back and try to figure out where it actually gets used on the right side. If we scroll down a bit you see it right here

Right above the function we have our pilot() method definition and right after that we call __decorate. The first argument is an array of all the decorators we are trying to apply to the method, the second is the Boat prototype, and the third is the key of the property we added our decorator to. The last argument is related to the property descriptor that we will talk about later.

--

--