Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add explicit error to __extends when base class is undefined #5794

Closed
Arnavion opened this issue Nov 25, 2015 · 9 comments · Fixed by #37283
Closed

Add explicit error to __extends when base class is undefined #5794

Arnavion opened this issue Nov 25, 2015 · 9 comments · Fixed by #37283
Labels
Help Wanted You can do this Suggestion An idea for TypeScript
Milestone

Comments

@Arnavion
Copy link
Contributor

We occasionally get people in the IRC channel asking about their transpiled JS failing with TypeError: undefined is not an object. It happens when accessing b.prototype inside __extends because the child class is before the base class, but they often think it's a bug in __extends. Would it make sense to detect if b is undefined at the start of the function and throw an appropriately worded error? Eg:

var __extends = this.__extends || function (d, b) {
    if (b === undefined) { throw new Error("The base class is not defined. Did you put the child class before the base class?"); }
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
};
@mhegazy mhegazy added the Suggestion An idea for TypeScript label Nov 26, 2015
@mhegazy
Copy link
Contributor

mhegazy commented Nov 26, 2015

would #4343 be sufficient to address the underlying problem?

@Arnavion
Copy link
Contributor Author

It seems to me that PR only detects child before base in the same file? Does it handle, say, base class imported from another module that also has circular reference so base class is still undefined?

@frankwallis
Copy link
Contributor

Coincidentally the circular referenced superclass issue came up on stack overflow just the other day: http://stackoverflow.com/questions/33897273/typescript-and-systemjs-circle-dependency/33905499#33905499

@mhegazy
Copy link
Contributor

mhegazy commented Dec 1, 2015

It seems to me that PR only detects child before base in the same file? Does it handle, say, base class imported from another module that also has circular reference so base class is still undefined?

you are correct, it does not handle circular references in modules, just in the same file, or if you are using --out.

@mhegazy mhegazy added the In Discussion Not yet reached consensus label Dec 1, 2015
@RyanCavanaugh
Copy link
Member

The other common case I see is that someone refactors into two script files and forgets to add a script tag for the file containing the base class.

@DavidKDeutsch
Copy link

Out of curiosity, has the implementation of __extends changed recently? Ever since upgrading to 1.8, I seem to get these run time errors a lot more. Not sure if it is just a coincidence or what.

@Arnavion
Copy link
Contributor Author

@DavidKDeutsch __extends is not the source of the problem (base class being undefined). It's the messenger. That's what this issue is about - of clarifying that the problem is not with __extends but with whether the classes are defined / loaded in the right order or not.

If you're seeing it more with 1.8 then it might be 1.8 changed the ordering of your classes such that the base class is undefined (although it sounds unlikely).

@DavidKDeutsch
Copy link

BTW, this can be especially confusing to developers when including other libraries that were also compiled with TypeScript, as the first file that defines __extends is where the error is thrown from.

@yssource
Copy link

I am having the same issue even if the class is used after the other:

BaseClass.ts:

module MyModule {
  export class Base {
    constructor() { }
  }
}

ChildClass.ts:

module MyModule {
  export class Child extends Base {
    constructor() { super(); }
  }
}

Generates:

/****************************************************************************
  Generated by T4TS.tt - don't make any changes in this file
****************************************************************************/

var MyModule;
(function (MyModule) {
  /** Generated from MyModule.Base **/
  var Base = (function () {
    function Base () {
    }
    return Base;
  })();
  MyModule.Base = Base;
})(MyModule || (MyModule = {}));

var __extends = (this && this.__extends) || function (d, b) {
    for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
    function __() { this.constructor = d; }
    d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};

var MyModule;
(function (MyModule) {
  /** Generated from MyModule.Child **/
  var Child = (function (_super) {
      __extends(Child, _super);
      function Child() {
          _super.apply(this, arguments);
      }
      return Child;
  })(MyModule.Base);
  MyModule.Child = Child;
})(MyModule|| (MyModule = {}));

It seems that the order is correct, although it doesn't look like it is working as expected.

But if I am merging two source files into one, then it is working well.

BaseClassAndChileClass.ts:

module MyModule {
  export class Base {
    constructor() { }
  }
  export class Child extends Base {
    constructor() { super(); }
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Help Wanted You can do this Suggestion An idea for TypeScript
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants