martin
martin

Reputation: 96899

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.

Upvotes: 1

Views: 2581

Answers (1)

Nitzan Tomer
Nitzan Tomer

Reputation: 164177

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()

Upvotes: 3

Related Questions