I apologize if it is a silly question. I am new with typescript and learning typescript decorators. I found a code: MethodDecorator to log the arguments and the result.
log decorator
function log (target: Object, key: string, descriptor: TypedPropertyDescriptor<any>) {
let originalMethod = descriptor.value;
descriptor.value = function (...args:any[]) {
//before
console.log(`${key} method called with args: ${JSON.stringify(args)}`);
let result = originalMethod.apply(this, args);
//after
console.log(`${key} method return value: ${JSON.stringify(result)}`);
}
return descriptor;
}
I am using @log with setId and getId methods in Book class
book.ts
class Book{
constructor(public id: number, public title: string, public publisher: string){}
@log
setId(id: number){
this.id = id;
}
@log
getId(): number{
return this.id;
}
}
All code works fine but getId returns undefined when i run this code.
let book = new Book(1, "Learn TypeScript", "O\'Reilly Media");
let favBookId = book.getId();
console.log("Book before setId: ");
console.log(book);
console.log("Favourite book id: "+favBookId);
book.setId(5);
console.log("Book after setId: ");
console.log(book);
console.log("Favourite book id: "+favBookId);
my tsconfig.json
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"removeComments": false,
"experimentalDecorators": true
}
}
To compile and run:
tsc -p ./
node book.js
Output:
getId method called with args: []
getId method return value: 1
Book before setId:
Book {id: 1, title: 'Learn TypeScript', publisher: 'O\'Reilly Media' }
Favourite book id: undefined
setId method called with args: [5]
setId method return value: undefined
Book after setId:
Book {id: 5, title: 'Learn TypeScript', publisher: 'O\'Reilly Media' }
Favourite book id: undefined
I am not able to understand why setId is working as I want and getId is not??
tsc -v: Version 1.8.10
I don't know why all the posts on the internet reference such examples, but I had problems of my own with the method decorator context regarding originalMethod.apply(this, args);
This indeed does NOT work AT ALL (I don't know if its a ts
bug or something though).
After trial an error, I found that the following solution worked, allowing you to have the correct context inside your base class:
function myDecorator(target: Object, key: string, descriptor: TypedPropertyDescriptor<any>) {
descriptor.value = function (...args:any[]) {
// whatever code suits you here...
// dont use "this", use "target"
let result = originalMethod.apply(target, args);
}
return descriptor;
}
Now this allows you to do:
export class Yeah {
@myDecorator()
helloWord() {
let n = 5;
return this.multiply(n);
}
multiply(a: number) {
return a * 2;
}
}
Cheers