装饰器加载顺序

类中不同声明上的装饰器将按以下规定的顺序应用:

  1. 参数装饰器,然后依次是方法装饰器,访问符装饰器,或属性装饰器应用到每个实例成员。
  2. 参数装饰器,然后依次是方法装饰器,访问符装饰器,或属性装饰器应用到每个静态成员。
  3. 参数装饰器应用到构造函数。
  4. 类装饰器应用到类。
tsconfig.json基本配置

代码输出目标版本要大于等于 ES5

{
  "compilerOptions": {
    "target": "ES5",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  },
  "exclude": [
    "node_modules"
  ],
}

装饰器方法签名

Class装饰器
/**
 * Class装饰器
 * @param target 类的构造函数
 * @returns      如果返回Function,会使用返回的Function替换原始Class构造函数
 */
declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
Method装饰器
/**
 * Method装饰器
 * @param target     对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
 * @param methodName 方法的名字
 * @param descriptor 方法的属性描述符(代码输出目标版本小于ES5,属性描述符将会是undefined)
 * @returns          如果返回一个值,它会被用作方法的属性描述符(如果代码输出目标版本小于ES5返回值会被忽略)
 */
declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
访问器装饰器
/**
 * Method装饰器
 * @param target     对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
 * @param methodName 方法的名字
 * @param descriptor 方法的属性描述符(代码输出目标版本小于ES5,属性描述符将会是undefined)
 * @returns          如果返回一个值,它会被用作方法的属性描述符
 */
declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) => PropertyDescriptor | void;

注意  TypeScript不允许同时装饰一个成员的getset访问器。取而代之的是,一个成员的所有装饰的必须应用在文档顺序的第一个访问器上。这是因为,在装饰器应用于一个属性描述符时,它联合了getset访问器,而不是分开声明的。

属性装饰器
/**
 * 属性装饰器
 * @param target       对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
 * @param propertyName 属性的名字
 */
declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;

注意  属性描述符不会做为参数传入属性装饰器,这与TypeScript是如何初始化属性装饰器的有关。 因为目前没有办法在定义一个原型对象的成员时描述一个实例属性,并且没办法监视或修改一个属性的初始化方法。返回值也会被忽略。因此,属性描述符只能用来监视类中是否声明了某个名字的属性。

参数装饰器
/**
 * 参数装饰器
 * @param target      对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
 * @param propertyKey 方法的名字
 * @param paramIndex 参数在函数参数列表中的索引
 */
declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;

注意参数装饰器只能用来监视一个方法的参数是否被传入。

文档更新时间: 2020-05-02 21:07   作者:lizw