- A practical guide to TypeScript decorators
- What are decorators?
- Getting started
- Types of decorators
- Class decorator
- Method decorator
- Property decorator
- Use cases for TypeScript decorators
- Calculate execution time
- Decorator factory
- Automatic error guard
- Conclusion
What are decorators?
Getting started
$ mkdir typescript-decorators
$ cd typescript decorators
$ npm init -y
$ npm install -D typescript @types/node
{
// ...
"scripts": {
"build": "tsc"
}
}
{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true
}
}
console.log("Hello, world!");
$ npm run build
$ node index.js
Hello, world!
$ npm install -D ts-node
{
"scripts": {
"build": "tsc",
"start": "ts-node index.ts"
}
}
$ npm start
Hello, world!
$ git clone https://github.com/rahmanfadhil/typescript-decorators.git
Types of decorators
const classDecorator = (target: Function) => {
// do something with your class
}
@classDecorator
class Rocket {}
const addFuelToRocket = (target: Function) => {
return class extends target {
fuel = 100
}
}
@addFuelToRocket
class Rocket {}
const rocket = new Rocket()
console.log(rocket.fuel) // 100
const myDecorator = (target: Object, propertyKey: string, descriptor: PropertyDescriptor) => {
// do something with your method
}
class Rocket {
@myDecorator
launch() {
console.log("Launching rocket in 3... 2... 1... 🚀")
}
}
const propertyDecorator = (target: Object, propertyKey: string) => {
// do something with your property
}
Use cases for TypeScript decorators
class Rocket {
@measure
launch() {
console.log("Launching in 3... 2... 1... 🚀");
}
}
import { performance } from "perf_hooks";
const measure = (
target: Object,
propertyKey: string,
descriptor: PropertyDescriptor
) => {
const originalMethod = descriptor.value;
descriptor.value = function (...args) {
const start = performance.now();
const result = originalMethod.apply(this, args);
const finish = performance.now();
console.log(`Execution time: ${finish - start} milliseconds`);
return result;
};
return descriptor;
};
const rocket = new Rocket();
rocket.launch();
Launching in 3... 2... 1... 🚀
Execution time: 1.0407989993691444 milliseconds
const changeValue = (value) => (target: Object, propertyKey: string) => {
Object.defineProperty(target, propertyKey, { value });
};
class Rocket {
@changeValue(100)
fuel = 50
}
const rocket = new Rocket()
console.log(rocket.fuel) // 100
class Rocket {
fuel = 50;
launchToMars() {
console.log("Launching to Mars in 3... 2... 1... 🚀");
}
}
const minimumFuel = (fuel: number) => (
target: Object,
propertyKey: string,
descriptor: PropertyDescriptor
) => {
const originalMethod = descriptor.value;
descriptor.value = function (...args) {
if (this.fuel > fuel) {
originalMethod.apply(this, args);
} else {
console.log("Not enough fuel!");
}
};
return descriptor;
};
class Rocket {
fuel = 50;
@minimumFuel(100)
launchToMars() {
console.log("Launching to Mars in 3... 2... 1... 🚀");
}
}
const rocket = new Rocket()
rocket.launchToMars()
Not enough fuel!
class Rocket {
fuel = 50;
@minimumFuel(100)
launchToMars() {
console.log("Launching to Mars in 3... 2... 1... 🚀");
}
@minimumFuel(25)
launchToMoon() {
console.log("Launching to Moon in 3... 2... 1... 🚀")
}
}
const rocket = new Rocket()
rocket.launchToMoon()
Launching to Moon in 3... 2... 1... 🚀
Conclusion