Martin Martin - 1 month ago 6
Javascript Question

Overriding methods from JavaScript function-based classes in TypeScript

I'm trying to override a object method defined in JavaScript (ES5) function-based class:

var JSClass = function() {
this.start = function() {
console.log('JSClass.start()');
}
}


Then calling
start()
method prints as expected:

let o1 = new JSClass();
o1.start();
// prints: JSClass.start()


However, if I try to extend this object with a TypeScript class such as:

class TSClass extends JSClass {
start() {
super.start();
console.log('TSClass.start()');
}

otherStart() {
this.start();
console.log('TSClass.otherStart()');
}
}


... then
TSClass::start()
is never called. Only the
start()
defined in
JSClass
.

let o2 = new TSClass();
o2.start();
o2.otherStart();


This prints just:

JSClass.start()
JSClass.start()
TSClass.otherStart()


I'd expect to print:

// by calling: o2.start();
JSClass.start()
TSClass.start()
// by calling: o2.otherStart();
JSClass.start()
TSClass.start()
TSClass.otherStart()


Is this by design? Then how can I extend ES5 object methods with TypeScript?

See live demo: https://jsfiddle.net/martinsikora/2sunkmq7/

Edit: I ended up using this.

class TSClass extends JSClass {

constructor() {
var oldStart = this.start;
this.start = () => {
oldStart.call(this);
console.log('TSClass.start()');
}
}
// ...
}


Now it works as expected.

Answer

Your problem is that you're adding the start method to JSClass as a class member instead of class method.
In order to make it a method you need to add it to the prototype:

var JSClass = function () {}

JSClass.prototype.start = function () {
    console.log('JSClass.start()');
}

Then this:

let o2 = new TSClass();
o2.start();
o2.otherStart();

Results in:

JSClass.start()
TSClass.start()
JSClass.start()
TSClass.start()
TSClass.otherStart()