Typescript: subclass/extend of Promise gives 'TypeError: undefined is not a promise' on run time

Typescript: subclass/extend of Promise gives 'TypeError: undefined is not a promise' on run time

我正在尝试取消我在 Typescript 中的 async 方法调用。

为此,我创建了一个新的 Promise 类型,它继承自 Promise:

class CancelablePromise<T> extends Promise<T>{

    public cancelMethod: () => void;
    constructor(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void) {
        super(executor);
        // Set the prototype explicitly.

        Object.setPrototypeOf(this, CancelablePromise.prototype);

    }

    //cancel the operation
    public cancel() {
        if (this.cancelMethod) {
            this.cancelMethod();
        }
    }
}

第一个版本没有Object.setPrototypeOf(..),但推荐on the TypeScript GitHub page

当我尝试使用它时,出现 运行 时间错误(没有编译错误):

class Test{

    async postFileAjax<T>(file: File): CancelablePromise <T> { 

        var promiseFunc = (resolve) => { resolve() };
        var promise = new CancelablePromise<T>(promiseFunc);
        promise.cancelMethod = () => { console.log("cancel!") };

        return promise;
    }
}

var test = new Test();
test.postFileAjax(null);

错误:

(unknown) Uncaught TypeError: undefined is not a promise
    at CancelablePromise.Promise (<anonymous>)
    at new CancelablePromise (<anonymous>:44:28)
    at __awaiter (<anonymous>:7:12)
    at Test.postFileAjax (<anonymous>:62:16)
    at <anonymous>:75:6
    at HTMLButtonElement.excuteButton.onclick (https://www.typescriptlang.org/play/playground.js:242)

我做错了什么?我看到在 ES6 中你可以将 Promise 子类化(参见 ),所以我希望在 TypeScript 中它也可以。

使用 Typescript 2.1 并以 es5 为目标

如果你运行TypeScript Playground中的代码,你可以看到相同的结果,点击"run"并检查控制台(F12)在新页面中。

如何解决这个 运行 时间错误?


PS:Whosebug 上的一个相关错误是 ,但这是一个编译错误并已解决。我已经拆分了编译和 运行time 错误。

我简化了你的例子;这运行没有错误:

interface CancelablePromise<T> extends Promise<T> {
    cancel: () => void;
}

class Test {
    postFileAjax<T>(file: File): CancelablePromise<T> {
        const promiseFunc = (resolve) => { resolve() };
        const promise = new Promise<T>(promiseFunc);
        const cancel = () => { console.log("cancel!") };
        const cancelablePromise = Object.assign(promise, { cancel });
        return cancelablePromise;
    }
}

const test = new Test();
const testPromise = test.postFileAjax(null);
testPromise.cancel();

TypeScript Playground

  • 我使用了接口继承而不是新的 class。
  • 我将 cancel 函数复制到 promise