下面的方法可以工作吗?
class A {
private mySecretNumber = 2;
decorate (f: (x :number) => number) {
return (x: number) => f(this.mySecretNumber * x);
}
@(this.decorate)
method (x: number) {
return x + 1;
}
}
我尝试过@this['decorate'],
@A['decorate']
,@A.decorate
找不到任何东西。
这是我的用例示例:https://kutt.it/uOxVgM。理想情况下,我只装饰getAbc()
和get123()
。
答案 0 :(得分:3)
您的问题有很多妙处。
第一件事是,是的,您确实可以使用方法作为修饰符,但不能通过编写@this.decorate
(在编译期间,this
将是globalThis
而不是{{ 1}}或A
(@A.decorate
不是静态方法,因此decorate
不存在)。问题的这一部分的正确答案是A.decorate
;这将完全确定您的想法。
第二件事是,当将装饰器应用于类的方法时,装饰器的参数不是方法函数本身,而是实际上具有3个参数:目标对象(应为@A.prototype.decorate
在我们的例子中),一个字符串(方法的名称,在我们的例子中为A.prototype
)和一个属性描述符对象。它还不返回新函数,但如果不为空,则应返回新的属性描述符。因此,在装饰器函数内部,您应该尝试修改目标对象,而不是尝试返回新函数。
将所有内容放在一起,一个有效的示例将是:
"method"
根据您的用例,我将使用以下方法。基本上,您使用静态装饰器来加载抽象的class A {
private mySecretNumber = 2;
decorate(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
var f = descriptor.value;
// Don't use arrow function here, otherwise "this"
// will not be the current A instance.
descriptor.value = function(x: number) {
return f(this.mySecretNumber * x);
};
Object.defineProperty(target, propertyKey, descriptor);
}
@A.prototype.decorate
method(x: number) {
return x + 1;
}
}
var a = new A();
console.log(a.method(3)); // 7
方法,该方法可以在子类中实现。我修改了上面的示例,以使您了解如何完成此操作。
decorate
答案 1 :(得分:0)
您可以通过使用类型约束来实现装饰器,以将其适用范围限制为实现mySecretNumber
属性的类。这样可以修复蔡慕尊explained so well的范围界定问题的语法和语义。
这就是我想要的:
class A {
mySecretNumber = 2;
@decorate
method(x: number) {
return x + 1;
}
}
function decorate<T extends { mySecretNumber: number }, K extends keyof T>(
target: T, key: K,
descriptor: T[K] extends (n: number) => number ? TypedPropertyDescriptor<(n: number) => number> : never
) {
const f = descriptor.value;
if (f) {
descriptor.value = function (this: T, x: number) {
return f(this.mySecretNumber * x);
};
}
return descriptor;
}
这可确保修饰的类具有类型mySecretNumber
的{{1}}属性,将该成员绑定到所需的number
,此外,还要确保修饰的方法具有正确的签名