使用打字稿装饰器来强制方法中的参数

Using typescript decorators to mandate a parameter in methods

在 typescript 项目中,大约有 2000 多个事件(方法)在用户触发操作和操作完成时触发。因此,对于操作完成时触发的所有事件,我想要某种性能指标,因此参数 'executionTime' 应该是强制性的。 我计划在所有那些必须将执行时间作为参数存在的事件之上添加 method decorator。下面是我的代码

class AllEvents {

    @performanceDecorator()
    public static firstEvent(param1: string, param2: string, executionTime: number): void {
        //some tasks...
    }

    @performanceDecorator()
    public static secondEvent(param1: string, param2: string): void {
        //some tasks...
    }

    @performanceDecorator()
    public static thirdEvent(param1: string, param2: string, executionTime: number): void {
        //some tasks...
    }
}

function performanceDecorator(value: boolean) {
    //..................
}

我是 typescript 的新手,无法弄清楚我应该在 函数 performanceDecorator 的主体中编写的代码,这样如果某些方法没有参数命名为 'executionTime',它会抛出错误。

扩展我之前的评论

由于您的场景中参数的数量无法固定,因此没有简单的方法可以确定您的参数中的哪一个是执行时间。

因此,使用预期的参数作为它的属性创建一个选项 class。像这样

class EventOptions {
    public params: string[];
    public executionTime?: number;
}

class AllEvents {

    @performanceDecorator
    public static firstEvent(eventOptions: EventOptions): void {
        //some tasks...
        console.log(eventOptions.params, eventOptions.executionTime);
    }

    @performanceDecorator
    public static secondEvent(eventOptions: EventOptions): void {
        //some tasks...
    }

    @performanceDecorator
    public static thirdEvent(eventOptions: EventOptions): void {
        //some tasks...
    }
}

在这里,我已将 executionTime 作为可选参数以适合您的用例。但是您可以继续将其设为必填字段,然后您将不需要装饰器来检查该字段的有效性。 Typescript 会为您完成。


然后转到装饰器:

函数装饰器有三个参数,

  • target 即调用 class,在本例中为 AllEvents
  • propertyKey 这是作为字符串的方法名称
  • descriptor 这是一个 属性 描述符。它具有与您的功能相关的所有元数据

我们可以将您的装饰器写成:

function performanceDecorator(
    target: Object,
    propertyKey: string,
    descriptor: PropertyDescriptor) {
        const originalMethod = descriptor.value;

        descriptor.value = (...args) => {
            if (!args[0].executionTime) {
                throw Error("Execution Time is missing!");
            }
            return originalMethod.apply(this, args);
        }
        return descriptor;
}

这里,我们先把原来的方法实现拿出来。然后使用条件检查 executionTime 参数的可用性。如果不存在,我们会抛出一个错误。如果存在,我们将调用原始方法实现。