📜  TypeScript装饰器

📅  最后修改于: 2021-01-11 12:52:33             🧑  作者: Mango

TypeScript装饰器

装饰器是一种特殊的声明,可以应用于类,方法,访问器,属性或参数。装饰器只是带有@expression符号前缀的函数,其中expression必须求值为一个函数,该函数将在运行时使用有关修饰声明的信息进行调用。

注意:装饰器是为ES7建议的实验功能。包括Angular 2在内的某些JavaScript框架已在使用它。装饰器在将来的版本中可能会更改。

要为装饰器启用实验性支持,我们必须在命令行tsconfig.json中启用experimentalDecorators编译器选项:

命令行

$tsc --target ES5 --experimentalDecorators

tsconfig.json

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

目的

TypeScript装饰器的目的是以声明的方式将注释和元数据添加到现有代码中。

装饰工厂

要自定义装饰器如何将其应用于声明,我们可以编写一个装饰器工厂。装饰器工厂是一个函数,该函数返回装饰器在运行时将调用的表达式。

装饰器工厂可以通过以下方式编写:

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

装饰组成

我们可以将多个装饰器应用于一个声明。以下示例有助于理解它。

在一行上

@f @g x

多行

@f
@g
x

装饰类型

TypeScript使用以下类型的装饰器:

1.类装饰器

在类声明之前定义了一个类装饰器,它告知类行为。类装饰器应用于该类的构造函数。类装饰器可用于观察,修改或替换类定义。如果类装饰器返回一个值,它将用给定的构造函数替换类声明。

例:

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

在上面的示例中,当执行@sealed装饰器时,它将密封构造器及其原型,因此我们无法继承Person类。

2.方法装饰器

在方法声明之前定义了方法装饰器。它应用于该方法的属性描述符。它可用于观察,修改或替换方法定义。我们不能在声明文件中使用方法装饰器。

方法装饰器函数的表达式接受三个参数。他们是:

  • 静态成员的类的构造函数或实例成员的类的原型。
  • 成员名称。
  • 成员的属性描述符。

例:

在以下示例中, @ log装饰器将记录新项目条目。

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

3.存取装饰器

访问器装饰器是在访问器声明之前定义的。它应用于访问器的属性描述符。它可用于观察,修改或替换访问者的定义。

注意:访问器是类声明的getter和setter属性。

访问器装饰器函数的表达式接受三个参数。他们是:

  • 静态成员的类的构造函数或实例成员的类的原型。
  • 成员名称。
  • 成员的属性描述符。

例:

在下面的示例中,访问器装饰器(@configurable)被应用于Employee类的成员。

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; }
}

4.财产装饰者

属性装饰器在属性声明之前定义。它类似于方法装饰器。属性装饰器和方法装饰器之间的唯一区别是它们不接受属性描述符作为参数,并且不返回任何内容。

属性装饰器函数的表达式接受两个参数。他们是:

  • 静态成员的类的构造函数或实例成员的类的原型。
  • 成员名称。

例:

在下面的示例中,@ ReadOnly装饰器会将name属性设置为只读,因此我们无法更改其值。

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

5.参数修饰符

参数修饰符在参数声明之前定义。它应用于类构造函数或方法声明的函数。不能在声明文件或任何其他环境上下文(例如,声明的类)中使用它。

参数装饰器函数的表达式接受三个参数。他们是:

  • 静态成员的类的构造函数或实例成员的类的原型。
  • 成员名称。
  • 函数?s参数列表中参数的索引。

例:

在下面的示例中,将参数修饰符(@required)应用于Person类的成员的参数。

class Person {
    msg: string;
    constructor(message: string) {
        this.msg = message;
    }
    @validate
    show(@required name: string) {
        return "Hello " + name + ", " + this.msg;
    }
}