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

 

posted @ 2019-03-20 13:00  MakeCoder  阅读(537)  评论(0编辑  收藏  举报