-
Notifications
You must be signed in to change notification settings - Fork 13.1k
Description
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.