在实现为箭头功能的类方法上使用TypeScript装饰器

问题描述 投票:0回答:1

免责声明:我之前曾在SO上发布过类似的问题。它们确实帮助我解决了一些TypeScript编译器问题。但是我找不到一个有效的,完整的代码示例。

问题:我想在某些类方法上使用TypeScript装饰器。但是问题是,如果我的方法被实现为箭头函数,我将无法使用它们。我已经根据一些文章和SO帖子修改了我的代码(在运行时,它们被更多地视为类属性),主要是

  1. 可选描述符descriptor?: TypedPropertyDescriptor<any>

  2. 返回为any

该编译器接受装饰器,并且我的代码正在执行而没有错误。但是我的装饰器代码无法正常工作。下面提供了简化的代码以供参考。使代码正常工作的任何帮助都将有所帮助。

注意:在普通实例方法上使用时,这绝对可以正常工作。

// Decorator declaration
export function LogPerf(
    message = '',
) {
    return function (
        target: any,
        key: string | symbol,
        descriptor?: TypedPropertyDescriptor<any>,
    ) {
        if (!descriptor) {
            console.log('Logging performance of property...'); // This log doesn't execute at runtime
            return;
        }

        // following log also doesn't work
        const original = descriptor.value;

        descriptor.value = function (...args: any[]) {
            const timeStartMilli: number = performance.now();

            const result = original.apply(this, args);

            const timeEndMilli: number = performance.now();

            console.log(`Call to ${key.toString()} took ${timeEndMilli - timeStartMilli} ms. Message: ${message}`);

            return result;
        };

        return descriptor as any;
    };
}


// Decorater use (on class method, implemented as arrow function)
public export SomeClass {

    @LogPerf()
    public myMethod = (
        data: MyData,
    ): Somehting => {
        // Do something with data
    }
}
typescript decorator arrow-functions typescript-decorator
1个回答
0
投票

问题是装饰器旨在应用于prototype对象。如果您检查了已转译的js,就会明白为什么它不起作用。

class SomeClass {
    @LogPerf()
    public myMethod = (
        data: MyData,
    ): Somehting => {
        // Do something with data
    }
}

/** transpiled to: */

class SomeClass {
    constructor() {
        this.myMethod = (data) => {
            // Do something with data
        };
    }
}

__decorate([
    LogPerf()
], SomeClass.prototype, "myMethod", void 0);

请参见,修饰符应用于SomeClass.prototype["myMethod"]。但是,当您将方法定义为箭头函数时,它将在构造函数中初始化并分配给this对象。

解决方法是:

  1. 将您的方法定义为prototype对象的常规函数​​,然后在初始化时绑定this
  2. 重载LogPerf()签名以接受如下所示的替代用法:
class SomeClass {
    public myMethod = LogPerf()((
        data: MyData,
    ): Somehting => {
        // Do something with data
    })
}
© www.soinside.com 2019 - 2024. All rights reserved.