TypeScript Decorators

A Decorator is a special kind of declaration that can be applied to classes, methods, accessor, property, or parameter. Decorators are simply functions that are prefixed @expression symbol, where expression must evaluate to a function that will be called at runtime with information about the decorated declaration.

Note
Note: Decorators are an experimental feature proposed for ES7. It is already in use by some of the JavaScript frameworks including Angular 2. The Decorators may change in future releases.

To enable experimental support for decorators, we must enable the experimentalDecorators compiler option either on the command line or in our tsconfig.json:

Command Line

$tsc --target ES5 --experimentalDecorators

tsconfig.json

Example
snippet
{
    "compilerOptions": {
        "target": "ES5",
        "experimentalDecorators": true
    }
}

Purpose

TypeScript Decorators serves the purpose of adding both annotations and metadata to the existing code in a declarative way.

Decorator Factories

To customize decorator how it is applied to a declaration, we can write a decorator factory. A decorator factory is a function which returns the expression that will be called by the decorator at runtime.

A decorator factory can be written in the following manner:

Example
snippet
function color(value: string) { // this is the decorator factory
    return function (target) { // this is the decorator
        // do something with 'target' and 'value'...
    }
}

Decorator Composition

We can apply multiple decorators to a declaration. The following examples help to understand it.

On a single line

Example
snippet
@f @g x

On multiple lines

Example
snippet
@f
@g
x

Types of Decorators

TypeScript uses the following types of Decorators:

TypeScript Decorators
  1. Class Decorators
  2. Method Decorators
  3. Accessor Decorators
  4. Property Decorators
  5. Parameter Decorators
Class Decorators

A class decorator is defined just before the class declaration, and it tells about the class behaviors. A class decorator is applied to the constructor of the class. A class decorator can be used to observe, modify, or replace a class definition. If the class decorator returns a value, it will replace the class declaration with the given constructor function.

Example
snippet
@sealed
class Person {
    msg: string;
    constructor(message: string) {
        this.msg = message;
    }
    show() {
        return "Hello, " + this.msg;
    }
}

In the above example, when @sealed decorator is executed, it will seal both the constructor and its prototype so that we cannot inherit the Person class.

Method Decorators

A Method Decorator is defined just before a method declaration. It is applied to a property descriptor for the method. It can be used to observe, modify, or replace a method definition. We cannot use method decorator in a declaration file.

The expression for the method decorator function accepts three arguments. They are:

  1. Either the constructor function of the class for a static member or the prototype of the class for an instance member.
  2. The member name.
  3. The Property Descriptor for the member.
Example

In the below example, the @log decorator will log the new item entry.

snippet
class Item {
    itemArr: Array;
    constructor() {
        this.itemArr = [];
        }
    @log
    Add(item: string): void {
       this.itemArr.push(item);
       }
    GetAll(): Array {
       return this.itemArr;
       }
}
Accessor Decorators

An Accessor Decorator is defined just before an accessor declaration. It is applied to the property descriptor for the accessor. It can be used to observe, modify, or replace an accessor's definitions.

Note
An accessor is a getter and setter property of the class declaration.

The expression for the accessor decorator function accepts three arguments. They are:

  1. Either the constructor function of the class for a static member or the prototype of the class for an instance member.
  2. The member name.
  3. The Property Descriptor for the member.
Example

In the below example, an accessor decorator (@configurable) is applied to a member of the Employee class.

snippet
class Employee {
    private _salary: number;
    private _name: string;

    @configurable(false)
    get salary() { return 'Rs. ${this._salary}'; }
    set salary(salary: any) { this._salary = +salary; }

    @configurable(true)
    get name() { return 'Sir/Madam, ${this._name}'; }
    set name(name: string) { this._name = name; }
}
Property Decorators

A property decorator is defined just before a property declaration. It is similar to the method decorators. The only difference between property decorators and method decorators is that they do not accept property descriptor as an argument and do not return anything.

The expression for the property decorator function accepts two arguments. They are:

  1. Either the constructor function of the class for a static member or the prototype of the class for an instance member.
  2. The member name.
Example

In the below example, the @ReadOnly decorator will make the name property as read-only, so we can't change its value.

snippet
class Company {
 @ReadOnly 
 name: string = "rookienerd.com";
}
let comp = new Company();
comp.name = 'SSSIT.com'; // Here, we can't change company name.
console.log(comp.name); // 'rookienerd.com'
Parameter Decorators

A parameter decorator is defined just before a parameter declaration. It is applied to the function for a class constructor or method declaration. It cannot be used in a declaration file or in any other ambient context (such as in a declared class).

The expression for the parameter decorator function accepts three arguments. They are:

  1. Either the constructor function of the class for a static member or the prototype of the class for an instance member.
  2. The member name.
  3. The index of the parameter in the function?s arguments list.
Example

In the below example, a parameter decorator (@required) is applied to the parameter of a member of the Person class.

snippet
class Person {
    msg: string;
    constructor(message: string) {
        this.msg = message;
    }
    @validate
    show(@required name: string) {
        return "Hello " + name + ", " + this.msg;
    }
}
Related Tutorial
Follow Us
https://www.facebook.com/Rookie-Nerd-638990322793530 https://twitter.com/RookieNerdTutor https://plus.google.com/b/117136517396468545840 #
Contents +