javascripttypescript1.8

Typescript method is return undefined with method decorator


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

Solution

  • 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