Reputation: 14198
I have a class decorator and would like to use it to apply another decorator to all methods within the class, but I am not quite sure how to apply a decorator programmatically without the @ syntax:
@LogAllMethods
class User {
greet() {
console.log('Hello')
}
}
function LogAllMethods(target) {
for (const key in Object.keys(target.prototype)) {
// apply LogMethod decorator
}
}
function LogMethod(target, key, descriptor) {
let method = descriptor.value
decriptor.value = function(...args) {
console.log(args)
method.apply(this, ...args)
}
}
Upvotes: 5
Views: 1948
Reputation: 249506
You basically just have to call the decorator function with the target, the key (method name) and the defined descriptor:
function LogAllMethods<T>(target: new (...params: any[]) => T) {
for (const key of Object.getOwnPropertyNames(target.prototype)) {
let descriptor = Object.getOwnPropertyDescriptor(target.prototype, key);
descriptor = LogMethod(target.prototype, key, descriptor);
if (descriptor) {
Object.defineProperty(target.prototype, key, descriptor);
}
}
}
function LogMethod(target: any, key: symbol | string, descriptor: TypedPropertyDescriptor<any> = undefined) {
if (descriptor) {
let method = descriptor.value;
if (method instanceof Function) {
descriptor.value = function (...args: any[]) {
console.log("Log", args)
method.apply(this, ...args);
}
}
return descriptor;
} else {
// descriptor is null for target es5 if the decorator is applied directly to the merhod
let method = target[key];
if (method instanceof Function) {
target[key] = function (...args: any[]) {
console.log("Log", args)
method.apply(this, ...args);
}
}
}
}
Upvotes: 3