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

Subclass extends Error is broken #14702

Closed
omochi opened this issue Mar 17, 2017 · 3 comments
Closed

Subclass extends Error is broken #14702

omochi opened this issue Mar 17, 2017 · 3 comments
Labels
Duplicate An existing issue was already created

Comments

@omochi
Copy link

omochi commented Mar 17, 2017

Summary

Subclass extends Error is broken.
If I define subclass and construct instance of it with new,
I get instance of Error but not instance of subclass.
So If I call instance method of this instance, it will crash.
And If I use instanceof operator to it, it return false.

TypeScript Version: 2.2.1

Code

// a.ts
class MyError extends Error {
    greet() {
        console.log("I am MyError!");
    }
}

let e = new MyError();
console.log(e instanceof MyError);
e.greet();

Compile and run

[omochi@omochi-MB ts-inst]$ $(npm bin)/tsc --version
Version 2.2.1
[omochi@omochi-MB ts-inst]$ node --version
v7.7.2
[omochi@omochi-MB ts-inst]$ $(npm bin)/tsc --target ES3 a.ts
[omochi@omochi-MB ts-inst]$ node a.js

Expected behavior:

Print true and I am MyError! on console.

Actual behavior:

Crash with this stacktrace.

false
/Users/omochi/temp/ts-inst/a.js:22
e.greet();
  ^

TypeError: e.greet is not a function
    at Object.<anonymous> (/Users/omochi/temp/ts-inst/a.js:22:3)
    at Module._compile (module.js:571:32)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:488:32)
    at tryModuleLoad (module.js:447:12)
    at Function.Module._load (module.js:439:3)
    at Module.runMain (module.js:605:10)
    at run (bootstrap_node.js:425:7)
    at startup (bootstrap_node.js:146:9)
    at bootstrap_node.js:540:3

My investigation

I tested this with some other configuration.

tsc version target version result
2.0.0 ES3 OK
2.0.0 ES2015 OK
2.2.1 ES3 NG
2.2.1 ES2015 OK
2.3.0-dev.20170316 ES3 NG
2.3.0-dev.20170316 ES2015 OK

What attract me is |2.0.0|ES3|OK|.

With 2.0.0, compiled constructor is below.

var MyError = (function (_super) {
    __extends(MyError, _super);
    function MyError() {
        _super.apply(this, arguments);
    }
    return MyError;
}(Error));

With 2.2.1, compiled constructor is below.

var MyError = (function (_super) {
    __extends(MyError, _super);
    function MyError() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    return MyError;
}(Error));

The difference is return value of MyError().
In 2.0.0, it returns undefined.
In 2.2.1, it returns instance from _super.apply(this, arguments) which is instance of Error but not MyError.

According what I hear, this change of constructor implementation is come from spec of ECMA2015.
But with ES2015 target compile, tsc generated raw JavaScript class syntax and It run correctly. (So compiled result javascript is almost same with source typescript)
So I think this behavior with ES3 target is bug.

@vvakame
Copy link
Contributor

vvakame commented Mar 17, 2017

related: #10762

@omochi
Copy link
Author

omochi commented Mar 17, 2017

@HerringtonDarkholme Thanks for information and sorry for my overlooking.
I tested this workaround and it runs expectedly.
Because earlier version 2.0.0 runs expectedly, I thought this current behavior is bug.
But I understood that this is regular result.

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Mar 17, 2017
@microsoft microsoft locked and limited conversation to collaborators Jun 21, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

4 participants