Generally, decorators in programming are used to add some additional meaning/function to a method, variable or a class.
I have used a lot of decorators while working in Spring Boot. I am currently learning Typescript and decorators fascinated me. Here is a small illustration of my use case for typescript decorators for functions.
Consider a Human class which maintains the stamina attribute and it is manipulated by run and rest methods. We need to capture the value of stamina before and after both, the actions - run and rest. I have added snippets for the code with and without decorators.
Code Before Decorators
class Human {
stamina: number;
constructor(stamina: number) {
this.stamina = stamina;
}
run(requiredStamina: number): number {
return (this.stamina -= requiredStamina);
}
rest(addedStamina: number): number {
return (this.stamina += addedStamina);
}
}
const human = new Human(10);
console.log(`Stamina before run: ` + human.stamina);
human.run(1);
console.log(`Stamina after run: ` + human.stamina);
console.log(`Stamina before rest: ` + human.stamina);
human.rest(12);
console.log(`Stamina after rest: ` + human.stamina);
console.log(`Stamina before run: ` + human.stamina);
human.run(20);
console.log(`Stamina after run: ` + human.stamina);
// Stamina before run: 10
// Stamina after run: 9
// Stamina before rest: 9
// Stamina after rest: 21
// Stamina before run: 21
// Stamina after run: 1
The above code looks good but soon the file would be cluttered with boilerplates.
Code with Decorators
class Human {
stamina: number;
constructor(stamina: number) {
this.stamina = stamina;
}
@log
run(requiredStamina: number): number {
return (this.stamina -= requiredStamina);
}
@log
rest(addedStamina: number): number {
return (this.stamina += addedStamina);
}
}
function log(
target: Object,
propertyKey: string,
descriptor: TypedPropertyDescriptor<any>
) {
const originalMethod = descriptor.value; // save a reference to the original method
// NOTE: Do not use arrow syntax here. Use a function expression in
// order to use the correct value of `this` in this method (see notes below)
descriptor.value = function (...args: any[]) {
// pre
console.log(`Stamina before ${propertyKey}: ` + args);
// run and store result
const result = originalMethod.apply(this, args);
// post
console.log(`Stamina after ${propertyKey}: ` + result);
// return the result of the original method (or modify it before returning)
return result;
};
return descriptor;
}
const human = new Human(10);
human.run(1);
human.rest(12);
human.run(20);
// Stamina before run: 1
// Stamina after run: 9
// Stamina before rest: 12
// Stamina after rest: 21
// Stamina before run: 20
// Stamina after run: 1
I have added comments in the snippet explaining the flow of data in the decorator! Simply put, decorators are invoked before the function is invoked and also has access to the arguments and the return value which could be used by the decorator.
There an N use cases for decorators in general. Let me know some interesting use case in the comment or reach out to me at radnerus93.
Top comments (8)
At Web Atoms, we are using decorator as follow,
Bindable Property
This turns member into property with getter/setter with ability to refresh the UI whenever it is set.
Dependency Injection
DI container automatically injects service for specified type.
Watch Decorator
Full name property automatically freshes the UI bound to this property when firstName or lastName changes.
Validation
Validate decorator helps in setting up validation that updates UI automatically when property is changed.
AJAX Services
Data Loading
This is a bit complex, it handles loading of data and canceling previous request automatically.
So whenever
search
is updated, this method is called automatically and UI refreshes it, it discards (aborts) previous ongoing request.For more information...
RetroFit inspired REST Services in Web Atoms Core
Akash Kava ・ Jul 5 '19 ・ 2 min read
ViewModel Decorators in Web Atoms for Xamarin.Forms
Akash Kava ・ Jun 14 ・ 2 min read
Simple and Complex Data Validation in Web Atoms
Akash Kava ・ Aug 28 '19 ・ 4 min read
Interesting implementations, Akash!
Great article🙌🙌
Thank you, Shreyasi✌️😉
I'm already familiar with decorators in angular. It was this reason behind that. Thanks for great article!
Thank you, Bravemaster❣️
Nice intro to the topic!
Glad this helped you :)