TypeScript: Return value of super() calls not used for `this`

If a constructor returns a value other than this, then in subclasses super() calls to that constructor should use the result as this in the subclass constructor.

I believe this is specified in 12.3.5.1, step 10 of SuperCall: http://www.ecma-international.org/ecma-262/6.0/index.html#sec-super-keyword

Getting this behavior correct is going to be very important for supporting Custom Elements, which takes advantage of this to initialize browser-allocated elements with user-written constructors. See https://w3c.github.io/webcomponents/spec/custom/#htmlelement-constructor

Note, Babel 6 implements this correctly.

TypeScript Version:

1.8.9

Code

class Foo {

  x : number;

  constructor() {
    return {
      x: 1,
    };
  }
}

class Bar extends Foo {

  y : number;

  constructor() {
    super();
    this.y = 2;
  }
}

let o = new Bar();
console.assert(o.x === 1 && o.y === 2);

Expected behavior:

No assertion error

The constructor for Bar should compile to this:

var Bar = (function (_super) {
    __extends(Bar, _super);
    function Bar() {
        var _this = _super.call(this);
        _this.x = 1;
        return _this;
    }
    return Bar;
}(Foo));

Actual behavior:

Assertion error

The constructor for Bar compiles to this:

var Bar = (function (_super) {
    __extends(Bar, _super);
    function Bar() {
        _super.call(this);
        this.x = 1;
    }
    return Bar;
}(Foo));

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 17 (7 by maintainers)

Most upvoted comments

if it worked you’d end up with new Bar() creating an object that doesn’t have any methods of Bar.

@jeffmcaffer This isn’t necessarily true, new Bar() can return a Bar even if it’s not returning this. It can easily type check - this has nothing to do with types. The return type of super() should be the return type of new in the super constructors interface.

For instance, this should fully type check:

class A {
  static _singleton : A;
  constructor() : A {
    if (!_singleton) {
      _singleton = this;
    }
    return _singleton;
  }
}

@mhegazy I’d like to point out that Typescript is in direct violation of the ECMAScript spec, and because of this you won’t be able to write Custom Elements in Typescript compiled to ES5*. I hope that if this behavior is “By Design” that the design can still be changed so that Typescript correctly implements ES2016 and is actually a superset rather a separate language.

*Targeting ES2015 should probably work, because ES2015 just works this way.