TypeScript: Incorrect transpiled constructor of derived classes
- Missing own class methods
- Missing relationship with own class (#10166)
TypeScript Version: master
Code
class C extends Error {
constructor() {
super('error');
}
m() {
}
}
console.log(new C().message);
console.log(new C().m);
console.log(new C() instanceof Error);
console.log(new C() instanceof C);
Expected behavior:
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 C = (function (_super) {
__extends(C, _super);
function C() {
var _that = _super.call(this, 'error');
if (_that) {
_that.__proto__ = this;
}
var _this = _that || this;
return _this;
}
C.prototype.m = function () {
};
return C;
}(Error));
console.log(new C().message); // 'error'
console.log(new C().m); // [Function]
console.log(new C() instanceof Error); // true
console.log(new C() instanceof C); // true
Actual behavior:
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 C = (function (_super) {
__extends(C, _super);
function C() {
return _super.call(this, 'error') || this;
}
C.prototype.m = function () {
};
return C;
}(Error));
console.log(new C().message); // 'error'
console.log(new C().m); // undefined
console.log(new C() instanceof Error); // true
console.log(new C() instanceof C); // false
About this issue
- Original URL
- State: closed
- Created 8 years ago
- Reactions: 1
- Comments: 38 (32 by maintainers)
Commits related to this issue
- update: sync with merge changes from last commit but ignore some pointless refactoring as 34c02a PS: duo to Microsoft/TypeScript#12123, 9 testcases don't pass test. But it will pass with future type... — committed to ts-webpack/webpack by e-cloud 8 years ago
- fix: test error due to Typescript limitation see https://github.com/Microsoft/TypeScript/issues/12123 for more details — committed to ts-webpack/webpack by e-cloud 8 years ago
- Add ts-invariant package. The assert(e instanceof InvariantError) test is currently broken due to these outstanding TypeScript bugs: https://github.com/Microsoft/TypeScript/issues/13965 https://gith... — committed to apollographql/invariant-packages by benjamn 5 years ago
- Work around TypeScript's failure to extend Error correctly. More relevant discussion: https://github.com/Microsoft/TypeScript/issues/12123 https://github.com/Microsoft/TypeScript/issues/12581 — committed to apollographql/invariant-packages by benjamn 5 years ago
- Remove unhelpful and slightly buggy enhanceErrorWithDocument function. Extending the built-in `Error` class in TypeScript results in a subclass whose `.prototype` is simply `Error.prototype`, rather ... — committed to apollographql/apollo-client by benjamn 5 years ago
- Remove unhelpful and slightly buggy enhanceErrorWithDocument function. Extending the built-in `Error` class in TypeScript results in a subclass whose `.prototype` is simply `Error.prototype`, rather ... — committed to apollographql/apollo-client by benjamn 5 years ago
My recommendation to get this working is to set the prototype explicitly on your instances. for instance:
The only change here from extending non-built-in classes is
Object.setPrototypeOf(this, MyError.prototype);alternatively, you can just set
this.__proto__instead of using Object.setPrototypeOf`@falsandtru Yes, they should lose methods.
In node 6:
Done!
@ahejlsberg @sandersn @vladima @RyanCavanaugh @DanielRosenwasser @mhegazy Can you resolve these problems before releasing 2.1? I believe TypeScript must not publish these problems via stable versions. At least these problems will break some code because of missing subclass methods.
Others can read about this breaking change and its solution on our wiki
Yes. We shouldn’t use
instanceofwithErrorand similar tricky classes without using native feature support of the class extending. We cannot handle/maintain that behavior.@aluanhaddad Also see #11304.
The thing is that extending
Errorand the like were previously broken as well, but in different ways. As a workaround, you can manually patch the prototype in your constructor, though I know that this is a less-than-satisfying answer.@falsandtru can you elaborate on the issue you mentioned when inheriting two levels deep or more?
I think so, but this solution possibly has no regression. So TypeScript can fix this bug using this solution. Additionally, the latest stable version doesn’t have this bug. So this bug will be the large regression, and it is too large to release as a stable version.
@falsandtru, one thing should be mentioned is that your expected behavior will generate a weird prototype chain.
However, since it’s hard to be fully compatible. That’s acceptable temporarily.