Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeScript - how to inherit class and override lambda method

I have an inherited class, and need the parent to have a virtual method, which is overridden in the child class. This method is called from the base constructor, and needs access to instance properties, so it needs to be a lambda function, so "this" is "_this". The problem is, overriding a lambda method does not work for me like overriding a non-lambda does. Is this possible? If not, I'd like to understand why.

Also, will "this" always be the same as "_this" when the method is only called from the constructor?

class Base {
    protected prop = null;
    constructor() {
        this.init();
        this.initLambda();
    }
    init() {
        console.log("Base init");
    }
    initLambda = () => {
        console.log("Base initLambda");
    }
}
class Derived extends Base {
    constructor() {
        super();
    }
    init() {
        console.log("Derived init");
    }
    initLambda = () => {
        //let x = this.prop;
        console.log("Derived initLambda");
    }
}

Output:
Derived init
Base initLambda

like image 545
user210757 Avatar asked Jul 28 '16 15:07

user210757


1 Answers

Well, you can't have that.
There's an issue that was opened but it was closed as "by design".

You should use regular methods:

class Base {
    protected prop = null;

    constructor() {
        this.init();
        this.initLambda();
    }

    init() {
        console.log("Base init");
    }

    initLambda() {
        console.log("Base initLambda");
    }
}

class Derived extends Base {
    constructor() {
        super();
    }

    init() {
        console.log("Derived init");
    }

    initLambda() {
        console.log("Derived initLambda");
    }
}

And then it will work.

As for keeping the right this, you can always pass a call to the method as an arrow function:

doit() {
    setTimeout(() => this.init(), 1);
}

Or use the Function.prototype.bind function:

setTimeout(this.init.bind(this));

Also, the _this thing that the typescript compiler produces is just a hack to polyfil the arrow functions for ES5, but if you change the target to ES6 then it won't use it.


Edit:

You can save the bound methods as members:

class Base {
    ...
    public boundInit: () => void;

    constructor() {
        ...
        this.boundInit = this.initLambda.bind(this);
        setTimeout(this.boundInit, 500);
    }

...

With that, when I do new Derived() this is what I get:

Derived init
Derived initLambda // after 200 millis

like image 166
Nitzan Tomer Avatar answered Oct 14 '22 09:10

Nitzan Tomer