Creating a subclass or extending a Promise in Typescript does not require referencing a constructor value that is compatible with Promises

I am currently working on a way to terminate my async method call in Typescript.

In order to achieve this, I decided to create a new type of Promise that extends from the standard Promise:

class CustomPromise<T> extends Promise<T>{

    private abortFunction: () => void;
    constructor(executor: (resolve: (value?: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void, abortFunction: () => void) {
        super(executor);
        this.abortFunction = abortFunction;
    }

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

However, when attempting to implement it like so:

async uploadFile<T>(file: File): CustomPromise<T> { ... }

I encounter the following error:

Error Build:Type 'typeof CustomPromise' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value.

If I specify the type and return the CustomPromise, as shown below, it compiles successfully:

async uploadFile<T>(file: File): Promise<T>  { 
     ...
     return CustomPromise(...);
}

What am I missing here? I have noticed that in ES6 you can subclass the Promise (refer to stackoverflow question), which makes me believe it should be possible in TypeScript too.

This project uses TypeScript version 2.1 with es5 targeting.

Answer №1

Initially, I found the error message to be a bit vague, but I realized that the constructor's signature must match exactly with the constructor of Promise.

I have eliminated the cancelMethod from the constructor and will assign it later. Here is the modified code:

class CancelablePromise<T> extends Promise<T>{

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

    }

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

You can call the method like this:

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

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

    return promise;
}

Answer №2

It is more efficient to utilize the utility type ConstructorParameters along with typeof instead of repeatedly copying types from constructor parameters:

class CustomPromise<T> extends Promise<T> {

  constructor(...args: ConstructorParameters<typeof Promise<T>>) {
    super(...args);
  }

}

Incorporating an additional argument can be a bit challenging

class CustomPromise<T> extends Promise<T> {

  constructor(...args: [...ConstructorParameters<typeof Promise<T>>, () => void]) {
    const [executor, cancel] = args
    super(executor);

    this.cancel = cancel;
  }

}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The function passed as a prop is unrecognized

I am having an issue with passing the function toggle and it is showing as undefined. Any advice on how to resolve this? function page() { const [open, setOpen] = React.useState(false); const handleToggle = () => { setOpen(!open); }; ...

How to create classes in typescript without utilizing the class keyword

As someone new to TypeScript, I have a curious question about classes. In pre-ES6 JavaScript, there were no classes. So, naturally, one would think it's possible to avoid using them in TypeScript as well. However, I am struggling to figure out the c ...

What is preventing the use of this promise syntax for sending expressions?

Typically, when using Promise syntax, the following code snippets will result in the same outcome: // This is Syntax A - it works properly getUser(id).then((user) => console.log(user) // Syntax B - also works fine getUser(id).then(console.log) However ...

Experiencing an issue with Jest - Error: unable to access property 'forEach' of null

After watching some tutorials, I decided to create a sample project in Jest for writing tests. In a TypeScript file, I included a basic calculation function like this: Calc.cs export class Calc { public add(num1: number, num2: number): number { ...

At runtime, the array inexplicably becomes null

Having recently ventured into the world of Ionic framework development, I have encountered a puzzling issue. At runtime, an array inexplicably gets nulled and I am struggling to pinpoint the root cause. export interface Days { name:string; } @Compon ...

Steps for removing the console warning message: "The use of enableRowSelect has been deprecated. Instead, please utilize rowSelection."

) I have integrated React Data Grid from https://adazzle.github.io/react-data-grid/ multiple times in my application. One thing I noticed is that there is a console warning related to a prop called "enableRowSelect" which indicates whether the prop is bein ...

The request.files property in express-fileupload is consistently coming back as undefined

I am trying to achieve the task of uploading a file from my browser and sending it via POST to an Express.js application, which will then download the file using express-fileupload. Here is the client-side JavaScript code I have written so far: // Triggere ...

Uh-oh! Looks like there was an issue trying to read properties of something that doesn't exist

I have a Spring Boot-Angular application and I am implementing server-side pagination. While my application is working fine, I am encountering a console error in TypeScript. Here is the code from user-list.component.ts: userList(): void{ this.userServ ...

Angular 5: dynamic component swapping

I am facing a challenge with dynamically placing components inside the view and need to switch their positions. For instance, I have dynamically created components with ids 1 and 2, as shown in the figure linked below. https://i.sstatic.net/hgxd2.jpg No ...

Transmit information using JSON format in Angular 8 using FormData

i am struggling with sending data to the server in a specific format: { "name":"kianoush", "userName":"kia9372", "email":"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bcd7d5ddd8ce85...@example.com</a>" } H ...

Issue: Attempting to assign a 'boolean' variable to a type of 'Observable<boolean>' is not compatible

I am currently working on the following code: import {Injectable} from '@angular/core'; import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree} from '@angular/router'; import {Observable} from 'rxjs' ...

How to require 2 out of 4 input fields in Angular using typescript

exploring the intricacies of design decisions, sub systems, frameworks, and libraries Hello! I am relatively new to Angular and have encountered a puzzling issue that I can't quite figure out. I could easily create a lengthy if statement to address i ...

There seems to be an issue with Material-UI and TypeScript where a parameter of type 'string' does not have an index signature in the type 'ClassNameMap<"container" | "navBar" | "section0">'

My current project is encountering a TS Error stating "(No index signature with a parameter of type 'string' was found on type 'ClassNameMap<"container" | "navBar" | "section0">'.)" The code below is used to assign styles to vari ...

Strategies for obtaining multiple instances of duplicated data within an array object

this array contains multiple instances of duplicate data var = [{id: 1, name:'jeff'}{id:1, name:'kent'}{id:2, name:'ynez'}{id:2, name:'cloe'}{id:3, name:'Ron'}{id:3, name:'chester'}] to achieve ...

Angular - Best practices for exchanging feedback between sibling components

The title may not be the most descriptive, but I struggled to find a better way to convey my issue. I've encountered a problem multiple times while working with angular. To illustrate, let's consider this scenario: Imagine having a main compone ...

Importing Angular libraries with the * symbol

One of the key modules in my library is sha256. To import it, I had to use the following syntax: import sha256 from 'sha256'; However, while researching this issue, I came across a question on Stack Overflow titled: Errors when using MomentJS ...

What is the best way to modify the KeyName in an object?

Having difficulty parsing an Object by changing keynames due to the error message "Element implicitly has an 'any' type because expression of type 'keyof SignInStore' can't be used to index type '{}'". interface SignInSto ...

Merge asynchronous sequences using built-in promises

I encountered a problem while trying to implement the logic for combining various types of iterables in a list, which includes Iterable, Iterator, AsyncIterable, and AsyncIterator. My goal is to combine them together to achieve the same output as RXJS&apos ...

Why use rxjs observables if they don't respond to updates?

I have an array of items that I turn into an observable using the of function. I create the observable before populating the array. However, when the array is finally populated, the callback provided to subscribe does not execute. As far as I know, th ...

Can functions be stored and invoked within a dictionary in TypeScript?

Currently, I'm in the process of refactoring some code and had a question regarding the possibility of declaring and initializing a dictionary that contains factory functions, with each function being associated with an enumerator key. This setup woul ...