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
OMG, I thought your problem is the same with me but it's not.
The problem is just caused by that you return nothing
when re-define the function.
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)}`);
}
descriptor.value = function (...args:any[]) {
//...
let result = originalMethod.apply(this, args);
//...
return result; //ADD HERE!!!
}
This is a full working example:
function log(msg: string): MethodDecorator {
return (
target: Object,
key: string | symbol,
descriptor: PropertyDescriptor
) => {
let originalMethod = descriptor.value;
descriptor.value = function (...args: any[]) {
//before
if (args.length >0) console.log(`${msg} ${key.toString()} method called with args: ${JSON.stringify(args)}`);
let result = originalMethod!.apply(this, args);
//after
if (result) console.log(`${key.toString()} method return value: ${JSON.stringify(result)}`);
};
return descriptor;
};
}
class Book {
constructor(
public id: number,
public title: string,
public publisher: string
) {}
@log('setting ')
setId(id: number) {
this.id = id;
}
@log('getting ')
getId(): number {
return this.id;
}
}
const a = new Book(1, "title", "publisher");
a.setId(2);
a.getId();
You can run it at typescript playground
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.