Introduction
With the introduction of Classes in Typescript and ES6, there now exits certain scenarios that require additional feature to support annotating or modifying classes and class members. Decorator provide a way to add both annotation and a meta-programming syntax for class declarations and members.
Node: To enable experimental support for decorator, you must enable the experimentalDecorators compiler option either on tsconfig.json:
tsc --target ES5 --experimentalDecorators
- compiler tsconfig.json:
{
"compilerOptions": {
"target": "ES5",
"experimentalDecorators": true
}
}
Decorators
A decorator kind of declaration that can be attached to a class declaration, method,accessor, property or parameter. Decorator use the form @expression, where expression must evaluate to a function that will be called at runtime with information about the decorated declaration.
function sealed(target) { // do something with 'target' ... }
Decorator Factories
A Decorator Factory is simply a function that returns the expression that will be called by the decorator at runtime.
function color(value: string) { // this is the decorator factory, it sets up // the returned decorator function return function (target) { // this is the decorator // do something with 'target' and 'value'... }; }
Decorator Composition
Multiple decorators can be applied to a declaration, for example on a single line:
@f @g x
On multiple lines:
function first() { console.log("first(): factory evaluated"); return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { console.log("first(): called"); }; } function second() { console.log("second(): factory evaluated"); return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { console.log("second(): called"); }; } class ExampleClass { @first() @second() method() {} } // Which would print this output to the console: first(): factory evaluated second(): factory evaluated second(): called first(): called
When multiple decorators apply to a single declaration, their evaluation is similar to function composition in mathematics. In this model, when composing functions f and g, the resulting composite (f ∘ g)(x) is equivalent to f(g(x)).
As such, the following steps are performed when evaluating multiple decorators on a single declaration in TypeScript:
The expressions for each decorator are evaluated top-to-bottom.
The results are then called as functions from bottom-to-top.
Class Decorators
A Decorator is declared just before a function declaration. The class decorator is applied to the constructor of the class and can be used modify, observe, or replace a class definition. A class decorator cannot be used in a declaration file, or in many other ambient context(such as on declare class).
if the class decorator returns a values, it will replace the class declaration with the provided constructor function.
@sealed class BugReport { type = "report"; //title= string; constructor(t: string) { this.title = t; } } function sealed(constructor: Function) { Object.seal(constructor); Object.seal(constructor.prototype); }
Note: the decorator does not change the TypeScript type