Repository navigation
Extending Promise gives runtime error: undefined is not a promise #15202
Copy link
Copy link
Closed
Labels
Description
Activity
- addedBugA bug in TypeScriptA bug in TypeScriptES6Relates to the ES6 SpecRelates to the ES6 Spec
on Apr 26, 2017 The issue here is that ES6 classes (e.g.
Promise) are not callable, the way ES5 built in classes (e.g.Array). The emitted code that the compiler produces usessuper.callwhich throws in ES6 engine.The fix here is to use
Reflect.constructif it exists instead ofcall.Reflect.constructis not something we can polifill, but we can assume if built-inPromiseis there,Refelect.constructis there too.Here is a proposal for that from Ron Buckton (@rbuckton):
var __construct = (this && this.__construct) || (typeof Reflect !== "undefined" && Reflect.construct ? function (self, target, args) { return self !== null && Reflect.construct(target, args, self.constructor) || self; } : function (self, target, args) { return self !== null && target.apply(self, args) || self; }); var PatchedPromise = (function (_super) { __extends(PatchedPromise, _super); function PatchedPromise(executor) { var _this = this; _this = __construct(this, _super, [executor]); return _this; } return PatchedPromise; }(Promise));
I have filed #15397 for this proposal.
FWIW, another workaround that seems to work is wrapping the promise in a class that's a "thenable". Here's one for a Deferred promise:
export default class Deferred<T> { private res: (value?: T | PromiseLike<T>) => void private rej: (reason?: any) => void private readonly promise: Promise<T> constructor() { this.promise = new Promise((resolve, reject) => { this.res = resolve this.rej = reject }) } then( onfulfilled?: (value: T) => T | PromiseLike<T>, onrejected?: (reason: any) => PromiseLike<never> ): Promise<T> { return this.promise.then(onfulfilled, onrejected) } catch(onRejected?: (reason: any) => PromiseLike<never>): Promise<T> { return this.promise.catch(onRejected) } resolve(value?: T | PromiseLike<T>): void { return this.res(value) } reject(reason?: any): void { return this.rej(reason) } }
Seems to work with
asyncand whatnot.Reacted by Julian Verdurmen, Adam Svanberg, Olivier Melcher and Nick Addisonclosing in favor of #15397
- locked and limited conversation to collaborators
on Jun 14, 2018
I also asks this on Stackoverflow, but I think this is a bug:
I'm trying to cancel my
asyncmethod call in Typescript.To do this, I have created a new
Promisetype, which inherits from Promise.My first version was without the
Object.setPrototypeOf(..), but I took it for hereTypeScript Version: 2.2.0, targeting ES5
Code
Expected behavior:
No runtime error, or compile error if not allowed.
And of course working promise if no error.
Actual behavior:
Got a run-time error
Error:
Link to playground