PLEASE NOTE: This issue was because of the use of GraphQL resolvers in running my decorated method. It meant that the scope of this
was undefined
. However, the basics of the question are useful for anyone hitting a problem with decorators.
This is a basic decorator I'm wanting to use (mine has more code in it):
const someDecorator = (argPassed: any) => {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
const originalMethod = descriptor.value;
// DO stuff here...
console.log(argPassed);
// Wrapping the original method
descriptor.value = (...args: any[]) => {
const result = originalMethod.apply(this, args);
return result;
};
};
};
I am using arrow functions within the decorator which is the only way i could get it to return some kind of scope, albeit different to a normal this
scope.
This is the class I'm using and the method I'm decorating:
class SomeClass {
constructor() {
}
@someDecorator('Passing this in...')
public doingSomething(argPassed: string) {
console.log(this); // Returns: { default: SomeClass { otherMethodInMyClass: [Function] } }
// Meaning i can't do this
// this.otherMethodInMyClass is not a function
this.otherMethodInMyClass(argPassed);
}
private otherMethodInMyClass = (argPassed: any) => {
// Let's go for it...
}
}
Currently the decorator passes back the scope of doingSomething
as:
{ default: SomeClass { otherMethodInMyClass: [Function] } }
When not using the decorator I get:
SomeClass { doingSomething: [Function], otherMethodInMyClass: [Function] }
Is this normal behaviour? If not, what am I doing wrong? If so, how do I allow my method to use its own scope as I am calling other methods after.
Update:
As @jcalz rightly mentioned, an arrow function doesn't get its own this
context. However when I used a non-arrow function across the decorator this
returned as undefined
.
Thanks in advance
In TypeScript, you can create decorators using the special syntax @expression , where expression is a function that will be called automatically during runtime with details about the target of the decorator. The target of a decorator depends on where you add them.
As of writing this guide, decorators are still an experimental feature in TypeScript. To enable this feature, set the experimentalDecorators compiler flag either on the command line or in your tsconfig. json file.
A Decorator is a special kind of declaration that can be applied to classes, methods, accessor, property, or parameter.
target: Constructor function of the class if we used decorator on the static member, or prototype of the class if we used decorator on instance member. In our case it is firstMessage which is an instance member, so the target will refer to the prototype of the Greeter class. propertyKey: It is the name of the property.
The issue in your question seems to be that you're using an arrow function as a method, which is not advisable since arrow functions don't get their own this
context.
You went on to say that changing this doesn't fix your issue, but I can't reproduce that:
const someDecorator = (argPassed: any) => {
return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
const originalMethod = descriptor.value;
console.log("ARGPASSED: ");
console.log(argPassed);
// anonymous function, not arrow
descriptor.value = function (...args: any[]) {
const result = originalMethod.apply(this, args);
return result;
};
};
};
class SomeClass {
constructor() { }
@someDecorator('Passing this in...')
public doingSomething(argPassed: string) {
console.log("THIS: ")
console.log(this);
this.otherMethodInMyClass(argPassed);
}
private otherMethodInMyClass = (argPassed: any) => { }
}
new SomeClass().doingSomething("abc");
// ARGPASSED:
// Passing this in...
// THIS:
// Object { otherMethodInMyClass: otherMethodInMyClass() }
Link to code in Playground
Looks good to me. If your issue persists, you might want to include more details about your configuration in your question. It always helps to make sure that code in your questions constitutes a reproducible example. Good luck!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With