-
启用装饰器
- 在tsconfig.json 中开启 experimentalDecorators: true
- 装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,访问符,属性,或者参数上
- 使用方式
@装饰器名称, 后面必须跟一个函数,会在运行时被调用
-
装饰器工厂
// 装饰器工厂函数 function f() { console.log("f(): evaluated"); return function (target, propertyKey: string, descriptor: PropertyDescriptor) { console.log("f(): called"); } } // 装饰器工厂函数 function g() { console.log("g(): evaluated"); return function (target, propertyKey: string, descriptor: PropertyDescriptor) { console.log("g(): called"); } } class C { @f() // 装饰器 @g() // 装饰器 method() {} } -
装饰器求职
- 类中不同声明上的装饰器将按以下规定的顺序应用:
- 参数装饰器,然后依次是方法装饰器,访问符装饰器,或属性装饰器应用到每个实例成员。
- 参数装饰器,然后依次是方法装饰器,访问符装饰器,或属性装饰器应用到每个静态成员。
- 参数装饰器应用到构造函数。
- 类装饰器应用到类。
- 类中不同声明上的装饰器将按以下规定的顺序应用:
-
类装饰器
// 类装饰器表达式会在运行时当作函数被调用,类的构造函数作为其唯一的参数。 // 如果类装饰器返回一个值,它会使用提供的构造函数来替换类的声明。 function classDecorator<T extends {new(...args:any[]):{}}>(constructor:T) { return class extends constructor { newProperty = "new property"; hello = "override"; } } @classDecorator class Greeter { property = "property"; hello: string; constructor(m: string) { this.hello = m; } } console.log(new Greeter("world")); -
方法装饰器
- 方法装饰器表达式会在运行时当作函数被调用,传入下列3个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
- 成员的属性描述符。
- 如果方法装饰器返回一个值,它会被用作方法的属性描述符。
// 先定义一个方法 function enumerable(value: boolean) { return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { descriptor.enumerable = value; }; } class Greeter { greeting: string; constructor(message: string) { this.greeting = message; } @enumerable(false) // 在类中将上面的方法设置为装饰器 greet() { return "Hello, " + this.greeting; } } - 方法装饰器表达式会在运行时当作函数被调用,传入下列3个参数:
-
访问器装饰器
- 访问器装饰器表达式会在运行时当作函数被调用,传入下列3个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
- 成员的属性描述符。
function configurable(value: boolean) { return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { descriptor.configurable = value; }; } 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; } } - 访问器装饰器表达式会在运行时当作函数被调用,传入下列3个参数:
-
属性装饰器
- 属性装饰器表达式会在运行时当作函数被调用,传入下列2个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
import "reflect-metadata"; const formatMetadataKey = Symbol("format"); function format(formatString: string) { return Reflect.metadata(formatMetadataKey, formatString); } function getFormat(target: any, propertyKey: string) { return Reflect.getMetadata(formatMetadataKey, target, propertyKey); } 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); } } - 属性装饰器表达式会在运行时当作函数被调用,传入下列2个参数:
-
参数装饰器
- 参数装饰器表达式会在运行时当作函数被调用,传入下列3个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 成员的名字。
- 参数在函数参数列表中的索引。
class Greeter { greeting: string; constructor(message: string) { this.greeting = message; } @validate greet(@required name: string) { return "Hello " + name + ", " + this.greeting; } } - 参数装饰器表达式会在运行时当作函数被调用,传入下列3个参数: