1. 装饰器是什么
- 它是一个表达式
 - 该表达式被执行后,返回一个函数
 - 函数的入参分别为 target、name 和 descriptor
 - 执行该函数后,可能返回 descriptor 对象,用于配置 target 对象
 
2. 装饰器的分类
- 类装饰器(Class decorators)
 - 属性装饰器(Property decorators)
 - 方法装饰器(Method decorators)
 - 参数装饰器(Parameter decorators)
 
2.1 类装饰器
declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
类装饰器顾名思义,就是用来装饰类的。它接收一个参数:
- target: TFunction - 被装饰的类
```typescript
function Greeter(greeting: string) {
return function (target: Function) {
  target.prototype.greet = function (): void {
}; }; }console.log(greeting);
 
@Greeter(“Hello TS!”) class Greeting { constructor() { // 内部实现 } }
let myGreeting = new Greeting(); myGreeting.greet(); // console output: ‘Hello TS!’;
<a name="myJAP"></a>## 2.2 属性装饰器```typescriptdeclare type PropertyDecorator = (target:Object,propertyKey: string | symbol ) => void;
属性装饰器顾名思义,用来装饰类的属性。它接收两个参数:
- target: Object - 被装饰的类
 - propertyKey: string | symbol - 被装饰类的属性名
 
2.3 方法装饰器
declare type MethodDecorator = <T>(target:Object, propertyKey: string | symbol,descriptor: TypePropertyDescript<T>) => TypedPropertyDescriptor<T> | void;
方法装饰器顾名思义,用来装饰类的方法。它接收三个参数:
- target: Object - 被装饰的类
 - propertyKey: string | symbol - 方法名
 descriptor: TypePropertyDescript - 属性描述符 ```typescript function LogOutput(target: Function, key: string, descriptor: any) { let originalMethod = descriptor.value;
let newMethod = function(…args: any[]): any { let result: any = originalMethod.apply(this, args); if(!this.loggedOutput) {
this.loggedOutput = new Array<any>();
} this.loggedOutput.push({
method: key,parameters: args,output: result,timestamp: new Date()
}); return result; }
descriptor.value = newMethod; }
class Calculator { @LogOutput double (num: number): number { return num * 2; } }
let calc = new Calculator(); calc.double(11); // console ouput: [{method: “double”, output: 22, …}] console.log(calc.loggedOutput);
<a name="y8dYb"></a>## 2.4 参数装饰器```typescriptdeclare type ParameterDecorator = (target: Object, propertyKey: string | symbol,parameterIndex: number ) => void
参数装饰器顾名思义,是用来装饰函数参数,它接收三个参数:
- target: Object - 被装饰的类
 - propertyKey: string | symbol - 方法名
 - parameterIndex: number - 方法中参数的索引值
``typescript function Log(target: Function, key: string, parameterIndex: number) { let functionLogged = key || target.prototype.constructor.name; console.log(The parameter in position ${parameterIndex} at ${functionLogged} has been decorated`); } 
class Greeter { greeting: string; constructor(@Log phrase: string) { this.greeting = phrase; } }
// console output: The parameter in position 0 // at Greeter has been decorated ```
