'How to call a method of a derived class in the constructor of this derived class

I have a piece of code that used to work in TypeScript a few years ago, but now is begin compiled using Microsoft.TypeScript.MSBuild 4.5.3 (as part of a Microsoft.NET.Sdk.Web NET 5.0 project) and no longer works. Previously code must have been compiled using an older version of this compiler, but I can't pinpoint which version (it was a TypeScript project in Visual studio 2017 or older). Here is a stripped down version of my code:

class MyArray extends Array<number>{
    constructor(x: number)
    {
        super();
        this.foo(x);
    }

    foo(x: number) {
        // Do stuff with x
    }
}

Creating a new instance of MyArray results in the exception: Uncaught TypeError: _this.foo is not a function

It appears to boil down to the constructor being compiled to:

var _this = _super.call(this) || this;
_this.foo(x)

If I understand it correctly, _this is an instance of an Array<number> and knows nothing of my foo method.

In the past the constructor would compile to:

_super.call(this);
this.foo(x)

which would work.

I desperately tried to find an answer to this problem on the internet, but had no luck. Adding to the confusion, intelisense and the compiler don't expect there to be a problem (probably because this code would work in a non-inherited class) and the debugger in the browser still firmly believes that this in my TypeScript constructor is an instance of MyArray rather than Array<number>.

Long story short, how can I call my foo method from the constructor of MyArray class?



Solution 1:[1]

Thanks to tips form Nalin Ranjan, I was able to figure out how to solve my problem. After switching my project to Microsoft.NET.Sdk.Web NET 5.0 I made no adjustments to the TypeScript compiler configuration. For some reason that meant my target was ES5 (I mistakenly expected it to default to a newer version of TypeScript and ES5 to somehow be a newer target). After changing the target to ES2017 (which I probably had in the old version of my project), everything started working as expected.

Solution 2:[2]

To be able to have a foo being called the way we want to with ES5 target, try this...

class MyArray  extends Array<number> {
    constructor(x: number) {
        super();
        this.foo(x);
    }

    // A property foo as arrow function, instead of a member function on the class
    foo = (x: number) => {
        // Do stuff with x
        console.log('foo called with', x);
    }
}

let c = new MyArray(6);

TS Playground

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jahu
Solution 2