TypeScript 装饰器
1. 类装饰器
应用于类构造函数,
*****参数是类的构造函数
function Path(path: string){ return function(target: Function){ !target.prototype.$Meta && (target.prototype.$Meta = {}) target.prototype.$Meta.baseUrl = path; }; } @Path("/hello") class HelloService{ constructor() } console.log(HelloService.prototype.$Meta);// 输出:{ baseUrl: '/hello' } let hello = new HelloService(); console.log(hello.$Meta) // 输出:{ baseUrl: '/hello' }
2. 方法装饰器
参数为:
1)对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象
2)成员的名字
3)成员的属性描述符
function GET(url: string) { return function (target, methodName: string, descriptor: PropertyDescriptor) { //tartget: 静态类来说是构造函数 //methodName: 方法名 //descriptor:方法对应的属性描述符 其对应的value就是方法体 } } class HelloService{ constructor(){} @GET("xx") static getUser(){} } console.log((<any>HelloService).$Meta);
3. 访问器装饰器
参数为:
1)对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象
2)成员的名字
3)成员的属性描述符
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; } } function configurable(value: boolean) { return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { descriptor.configurable = value; }; }
4. 属性装饰器
参数列表
1)对于静态成员来说是类的构造函数,对于实例成员是类的源性对象
2)成员的名字
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); } } 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); }
5. 参数装饰器
参数列表:
1)对于静态成员来说是类的构造函数,对于实例成员是类的源性对象
2)成员的名字
3)参数在函数参数列表中的索引
class Greeter { greeting: string; constructor(message: string) { this.greeting = message; } @validate greet(@required name: string) { return "Hello " + name + ", " + this.greeting; } } import "reflect-metadata"; const requiredMetadataKey = Symbol("required"); function required(target: Object, propertyKey: string | symbol, parameterIndex: number) { let existingRequiredParameters: number[] = Reflect.getOwnMetadata(requiredMetadataKey, target, propertyKey) || []; existingRequiredParameters.push(parameterIndex); Reflect.defineMetadata(requiredMetadataKey, existingRequiredParameters, target, propertyKey); } function validate(target: any, propertyName: string, descriptor: TypedPropertyDescriptor<Function>) { let originalMethod = descriptor.value; descriptor.value = function () { let requiredParameters: number[] = Reflect.getOwnMetadata(requiredMetadataKey, target, propertyName); if (requiredParameters) { for (let parameterIndex of requiredParameters) { if (parameterIndex >= arguments.length || arguments[parameterIndex] === undefined) { throw new Error("Missing required argument."); } } } return originalMethod.apply(this, arguments); } }
举个例子:
const CheckNullKey = Symbol(); const Router = Symbol(); function CheckNull(target: any, name: string, index: number) { target[Router] = target[Router] || {}; target[Router][name] = target[Router][name] || {}; target[Router][name].params = target[Router][name].params || []; target[Router][name].params[index] = CheckNullKey; } function Check(target: any, name: string, descriptor: PropertyDescriptor) { let method = descriptor.value; descriptor.value = function() { let params = target[Router][name].params; if (params) { for (let index = 0; index < params.length; index++) { if (params[index] == CheckNullKey && (arguments[index] === undefined || arguments[index] === null)) { throw new Error("Missing required arguments"); } } } return method.apply(this, arguments); } } class Controller { @Check public getContent( @CheckNull id: string): string { console.info(id); return id; } } new Controller().getContent(null);