Understanding TypeScript decorators.

JavaScript is an awesome programming language. And TypeScript has done a great job at filling in the gaps of JavaScript. Not only does it add types, it also implements a few extra features which aren’t there in JavaScript yet. One of them are decorator…


This content originally appeared on DEV Community and was authored by Siddharth

JavaScript is an awesome programming language. And TypeScript has done a great job at filling in the gaps of JavaScript. Not only does it add types, it also implements a few extra features which aren't there in JavaScript yet. One of them are decorators.

What is a decorator?

Decorators have been there in programming languages for a long time. Definitions vary, but in short a decorator is a pattern in JavaScript which is used to wrap something to change it's behavior.

In both JavaScript and TypeScript this is an experimental feature. In JavaScript, it's still a Stage 2 proposal and you can only use it via transpilers like Babel.

I've decided to explain TypeScript decorators because in TypeScript it has been standardized, and both are basically the same anyways.

Using Decorators

This is a very simple example of how to use a decorator:

const myDecorator = (thing: Function) => {
    // return something
}

@myDecorator
class Thing {

}

First we define a function myDecorator, and then we "decorate" a variable (our class Thing in this case) with the decorator. The decorator can return pretty much anything, but most of the time it used to set properties on the class, etc. Here's a real life sample:

const defaultGun = (gun: Function) => class extends gun {
    ammo = 10
}

@defaultGun
class Gun {

}

Now, Gun will have a ammo property by default.

const gun = new Gun()
console.log(car.ammo) // => 10

Decorating functions

Another place we can use decorators is in class methods. This time, the decorator gets three arguments.

const myDecorator = (parent: Function, prop: string, descriptor: PropertyDescriptor) => {
    // return something
}

class Gun {
    @myDecorator
    fire() {
        console.log('Firing in 3... 2... 1... ?')
    }
}

The first param contains the class where the decorated thing exists (in our case Gun). The second param is the name of the property decorated (in our case fire). The last is the property descriptor, which is the output of Object.getOwnPropertyDescriptor(parent[prop])

Properties

You can also decorate properties. It is pretty much the same as function decorators, except there is no third parameter:

const myDecorator = (parent: Function, prop: string) => {
    // return something
}

More places to decorate

You can also decorate in more places. Check out the documentation to learn more.

Use cases

There are many uses for decorators. We'll go over some here.

Calculate performance

class Gun {
    @time
    fire() {
        console.log('Firing in 3... 2... 1... ?')
    }
}

time could be a function which calculates the execution time.

Decorator factory

Decorators can also be factories, which returns a function which is the actual decorator. This can be useful when you want your decorators need any arguments.

// The decorator factory
const change = value => {
    // The factory will return a new handler
    return (target, prop) => {
        // We replace the old value with a new one
        Object.defineProperty(target, prop, {value})
    }
}

Then when "decorating" we just need to decorate like a function:

class Gun {
    @change(20)
    ammo = 10
}

const gun = new Gun();
console.log(gun.ammo) // => 20

A practical example: error handling

Let's use what we have learned to solve a real world problem.

class Gun {
    ammo = 0

    fire() {
        console.log('Firing in 3... 2... 1... ?')
    }
}

Let's assume that to fire, we need at least 1 ammo. We can make a check for that using a decorator:

const minAmmo = (ammo: number) => (
    target: Object,
    prop: string,
    descriptor: PropertyDescriptor
) => {
    const original = descriptor.value;

    descriptor.value = function (...args) {
        if (this.ammo >= ammo) original.apply(this);
        else console.log('Not enough ammo!');
    }

    return descriptor;
}

minAmmo is a factory decorator which takes a parameter ammo which is the minimum ammo needed.

We can use implement it in our Gun class.

class Gun {
    ammo = 0

    @minAmmo(2)
    fireTwice() {
        console.log('Firing in 3... 2... 1... ?')
    }
}

Now if you run fire(), it won't fire because we don't have enough ammo.

The nice thing is that we can just reuse this without rewriting an if statement. Suppose we need a fireOnce method. We can easily implement that.

class Gun {
    ammo = 0

    @minAmmo(2)
    fireTwice() {
        console.log('Firing twice in 3... 2... 1... ?')
    }

    @minAmmo(1)
    fireOnce() {
        console.log('Firing once in 3... 2... 1... ?')
    }
}

This kind of decorator can be really useful authentication. authorization, and all the other good stuff.

Liked the post? ❤️ it. Loved it? ? it.

If you want more people to learn about this, share this on Twitter


This content originally appeared on DEV Community and was authored by Siddharth


Print Share Comment Cite Upload Translate Updates
APA

Siddharth | Sciencx (2021-09-29T08:57:44+00:00) Understanding TypeScript decorators.. Retrieved from https://www.scien.cx/2021/09/29/understanding-typescript-decorators/

MLA
" » Understanding TypeScript decorators.." Siddharth | Sciencx - Wednesday September 29, 2021, https://www.scien.cx/2021/09/29/understanding-typescript-decorators/
HARVARD
Siddharth | Sciencx Wednesday September 29, 2021 » Understanding TypeScript decorators.., viewed ,<https://www.scien.cx/2021/09/29/understanding-typescript-decorators/>
VANCOUVER
Siddharth | Sciencx - » Understanding TypeScript decorators.. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2021/09/29/understanding-typescript-decorators/
CHICAGO
" » Understanding TypeScript decorators.." Siddharth | Sciencx - Accessed . https://www.scien.cx/2021/09/29/understanding-typescript-decorators/
IEEE
" » Understanding TypeScript decorators.." Siddharth | Sciencx [Online]. Available: https://www.scien.cx/2021/09/29/understanding-typescript-decorators/. [Accessed: ]
rf:citation
» Understanding TypeScript decorators. | Siddharth | Sciencx | https://www.scien.cx/2021/09/29/understanding-typescript-decorators/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.