免责声明:我之前曾在SO上发布过类似的问题。它们确实帮助我解决了一些TypeScript
编译器问题。但是我找不到一个有效的,完整的代码示例。
问题:我想在某些类方法上使用TypeScript
装饰器。但是问题是,如果我的方法被实现为箭头函数,我将无法使用它们。我已经根据一些文章和SO帖子修改了我的代码(在运行时,它们被更多地视为类属性),主要是
可选描述符descriptor?: TypedPropertyDescriptor<any>
返回为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
}
}
问题是装饰器旨在应用于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
对象。
解决方法是:
prototype
对象的常规函数,然后在初始化时绑定this
。LogPerf()
签名以接受如下所示的替代用法:class SomeClass {
public myMethod = LogPerf()((
data: MyData,
): Somehting => {
// Do something with data
})
}