This is the 17th day of my participation in the August More text Challenge. For details, see: August More Text Challenge

preface

In this chapter we’ll focus on decorators in TS. A decorator is a special type of declaration that can be attached to a class declaration, method, accessor, property, or parameter. Decorators use the form @expression. Expression must be evaluated to be a function that is called at runtime, passing in the decorated declaration information as an argument.

Why use decorators?

Decorators are also a design pattern. In daily development, sometimes we always have such needs, in front of the function, to a type of calibration, data filtering, the limit operation, such as the number of calls for functions, belong to the business code, direct transformation doesn’t fit, so if you can join a middle tier, to help deal with some special logic? Decorators are the first choice.

Study on TS decorator

Let’s first look at the syntax of the decorator:

function helloWord(target: any) {
    console.log('hello Word! ');
}

@helloWord
class HelloWordClass {}Copy the code

Upon execution, hello Word! A decorator function is a self-executing function. However, this self-execution is done at compile time, not at run time. This means that decorators can run code during the compile phase.

Method decorator

Method decorators are declared before (immediately after) the declaration of a method. It is applied to the method property descriptor and can be used to monitor, modify, or replace the method definition. Method decorators cannot be used in declaration files (.d.ts), overloads, or any external context (such as declare classes).

The method decorator expression is called at runtime as a function, passing the following three arguments:

  1. Class constructor for static members, prototype object for instance members.
  2. Names of members.
  3. The attribute descriptor for the member.
class Greeter {
    greeting: string;
    constructor(message: string) {
        this.greeting = message;
    }

    @enumerable(false)
    greet() {
        return "Hello, " + this.greeting; }}Copy the code

Accessor decorator

Accessor decorators are declared before (right next to) a accessor declaration. Accessor decorators apply to an accessor’s property descriptor and can be used to monitor, modify, or replace the definition of an accessor. Accessor decorators cannot be used in declaration files (.d.ts) or in any external context (such as declare classes).

class Point {
    private _x: number;
    private _y: number;
    constructor(x: number, y: number) {
        this._x = x;
        this._y = y;
    }

    @configurable(false)
    get x() { return this._x; }

    @configurable(false)
    get y() { return this._y; }}Copy the code

Property decorator

A property decorator is declared before (immediately following) a property declaration. Property decorators cannot be used in declaration files (.d.ts), or in any external context (such as declare classes).

class Greeter {
    @format("Hello, %s")
    greeting: string;

    constructor(message: string) {
        this.greeting = message;
    }
    greet() {
        let formatString = getFormat(this."greeting");
        return formatString.replace("%s".this.greeting); }}Copy the code

Bable configuration

To enable the experimentalDecorators feature, you must enable the experimentalDecorators compiler option on the command line or in tsconfig.json:

tsconfig.json:

{
    "compilerOptions": {
        "target": "ES5"."experimentalDecorators": true}}Copy the code

summary

Based on our theory and practice, we can draw the following conclusions:

  • Execution order for multiple argument decorators: start with the last argument, but class decorators are always executed last.

  • Method and method parameter decorators are executed first.

  • Method and property decorators, whichever comes first. Because the parameters are part of the method, they are always executed right next to the method.