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.