TypeScript 装饰器

博客主要介绍了JavaScript中各类装饰器及其参数。包括类装饰器、方法装饰器、访问器装饰器、属性装饰器和参数装饰器,详细说明了每种装饰器的参数情况,如对于静态和实例成员参数的不同,还给出了示例的转载链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

 

转载于:https://www.cnblogs.com/KruceCoder/p/10564248.html

### TypeScript 装饰器概述 装饰器是一种特殊类型的声明,能够附加到类声明、方法、访问器、属性或参数上。它们使用 `@expression` 这样的语法糖衣形式来实现,其中表达式求值后必须返回一个函数,该函数会在运行时被调用并传入相应的上下文。 为了使装饰器生效,项目配置文件 `tsconfig.json` 中需设置 `"experimentalDecorators": true`[^4]。 ### 类装饰器实例 类装饰器应用于类构造函数,通常用来监视、修改或替换类定义。下面是一个简单的例子: ```typescript function logged(constructor: Function) { console.log('Class:', constructor.name); } @logged class Greeter { greeting: string; constructor(message: string) { this.greeting = message; } greet() { return 'Hello, ' + this.greeting; } } ``` 当创建 `Greeter` 的新实例时,会先执行 `logged` 函数,并打印出类的名字[^1]。 ### 方法装饰器示例 方法装饰器用于修饰原型上的方法。此装饰器接受三个参数:目标对象(对于静态成员来说是类本身;对于实例成员则是类的原型)、成员名字以及描述符。通过这个机制可以在不改动原始逻辑的前提下增强现有行为。 ```typescript // 定义一个简单的方法装饰器 function enumerable(value: boolean) { return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) { descriptor.enumerable = value; }; } class Example { @enumerable(false) private method() { console.log('This is a non-enumerable method'); } } ``` 在这个案例里,`method()` 将不会出现在枚举操作的结果集中,比如 `for...in` 循环中[^3]。 ### 应用场景说明 利用装饰器模式的优势之一在于能够在不影响原代码结构的情况下增加额外的功能。这不仅提高了代码的可维护性和灵活性,同时也增强了程序设计的表现力和清晰度[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值