Decorators in TypeScript
Overview
Decorators are an experimental feature of TypeScript (and also a JavaScript stage 2 feature, meaning they will be soon included in standard JS) allowing you to inject specific behaviors to classes, properties, methods, accessors or parameters.
This features allow some kind of meta-programming and dependency injection, called at runtime.
This is mainly used in libs to add specific behaviors to your own code.
For example, TypeORM, an ORM lib, use this feature to give a nice way for
users to annotate their models, the dedicated char to use decorator is @
:
@Entity()
export class Person {
@PrimaryGeneratedColumn()
id: number;
@Column()
lastname: string;
}
Example
This features needs to be explicitly set as enabled in your tsconfig.json
:
"experimentalDecorators": true
Decorators are just functions, for example, here is a property decorator
class Decorator {
// Call to the emoji decorator with a string passed as argument
@emoji("🦍")
name: string = "";
constructor(name: string) {
this.name = name;
}
}
// The actual decorator code, this is, in fact a decorator factory
// It's a high order function returning the actual decorator
// It's a common and nice way to have access to a larger scope to
// play with the args passed as params (emojo, here)
function emoji(emojo: string) {
// Return the actual decorator
return function (target: any, key: string) {
// get the actual value
let val = target[key];
// customize getter
const getter = () => {
return val;
}
// and setter, to add some nice emojos
const setter = (next: string) => {
val = ${emojo} ${next} ${emojo};
}
// Apply thoose changes to the actual object property
Object.defineProperty(target, key, {
get: getter,
set: setter,
enumerable: true,
configurable: true
});
}
}
const example = new Decorator("hello");
console.log(example.name);
Even if this example is quite useless, it gives an overview of the possibilities of this feature.
More ressources can be found in the Handbook