79

I've a sample Promise function like below. On success I return a number and on false I return string. The compiler is complaining to specify some kind of generic type to the promise. In this case what type I've to specify? Do I've to specify like Promise<number> or Promise<number | string>?

function test(arg: string): Promise {
    return new Promise((resolve, reject) => {
        if (arg === "a") {
            resolve(1);
        } else {
            reject("1");
        }
    });
}
CC BY-SA 3.0
2

3 Answers 3

159

The generic type of the Promise should correspond to the non-error return-type of the function. The error is implicitly of type any and is not specified in the Promise generic type.

So for example:

function test(arg: string): Promise<number> {
    return new Promise<number>((resolve, reject) => {
        if (arg === "a") {
            resolve(1);
        } else {
            reject("1");
        }
    });
}
CC BY-SA 3.0
4
  • 5
    Is there a way to specify the type of the error case? E.g. I have a promise which, if rejects, rejects with a custom object. Can I specify the type of the rejection value using Promise<T> builtin generic type? Thank you!
    – tonix
    Commented Aug 1, 2020 at 21:08
  • 2
    @tonix For the exact reason that you are rejecting with a custom object (the flexibility to do so) is because Promise has any error type. The error type can't be constrained because any running code within the promise can throw anything, not just normal Error. (See developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… . It's throw expression). Since the promise is a generic object which can't control what runs inside it, and it would also be tedious/over-expectant to expect you (the dev) to control what runs inside it, the error type can't be constrained. Commented Oct 7, 2020 at 13:53
  • 3
    @GeorgePantazes : I'm not convinced that it would be tedious if one could optionally specify the reject type. Also, one can't control what runs inside for a resolved value either, but still one can specify it. Commented May 1, 2021 at 23:13
  • 1
    @BrettZamir a relevant answer to tonix's question is here (also has a link to an elaboration about TS's type checker): stackoverflow.com/a/50071254/6103242. As I got it, the reason why Error's type can't be constrained is because the type checker in general can't differentiate the types of what's been thrown. That is, it can enforce a type of a returning value, but it can not enforce the type of a thrown value (whether in promises or not – consider a catch statement in TS).
    – vladZams
    Commented Jan 5 at 4:03
6

You could define a custom Promise type that actually also cares about the type of the rejection. You can also just give it a single type and the reject type will be any, like in a normal promise.


type CustomPromise<T, F = any> = {
    catch<TResult = never>(
        onrejected?: ((reason: F) => TResult | PromiseLike<TResult>) | undefined | null
    ): Promise<T | TResult>;
} & Promise<T>;

function test(arg: string): CustomPromise<number, string> {
    return new Promise((resolve, reject) => {
        if (arg === "a") {
            resolve(1);
        } else {
            reject("1");
        }
    });
}

const myPromise = test("a");
myPromise.then((value) => {}); //value is of type `number`
myPromise.catch((reason) => {}); //reason is of type `string`
CC BY-SA 4.0
1
-1
function test(arg: string) {
   return new Promise((resolve: (value: number) => void, reject) => {
    if (arg === "a") {
        resolve(1);
    } else {
        reject("1");
    }
  });
}
CC BY-SA 4.0
1
  • 20
    Code only answers can generally be improved by adding some explanation of how and why they work. This is even more important when adding an answer to an older question with an accepted answer. Point out what new aspect of the question your answer addresses and note if the passage of time and introduction of new versions impacts the answer. Commented Jul 4, 2020 at 5:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.