Home > other >  Typescript return multiple promise types
Typescript return multiple promise types

Time:10-10

I have have some types like tihs

export interface Result<T> { data: T};
export type ErrorResult = Result<string>;
export type ErrorResponse = Promise<ErrorResult>;
export type SuccessResult = Result<any>;
export type SuccessResponse = Promise<SuccessResult>;

Why won't TS let me write a function like

export async function stuff(): ErrorResponse | SuccessResponse {}

It will only let me do

export async function stuff(): Promise<ErrorResult | SuccesResult> {}

CodePudding user response:

In JavaScript, a function declared as async always returns a Promise. That promise can be await-ed to retrieve a value of the internal type. (Read more on MDN)

E.g.

async function getName() {
  // Example internals..
  return "Celine";
}

const theNamePromise = getName();
//    ^^ This is a Promise<string>

const theName = await getName();
//    this is a string ("Celine")

Edit: More specific to your example:

(Note, I don't actually have a convincing answer here. But I did some tinkering and found some mildly interesting things. The below is a very short write-up of what I found, and here is the example code I was playing with)

It's important to note that Promise<string> | Promise<number> and Promise<string | number> are close, but not entirely equivalent as far as TypeScript is concerned.

To explain with an example, suppose we take your Result<T> type and used it similarly:

function getResult(): Result<string> | Result<number> {
    // This return statement yields a TS error
    return {
        data: Math.random() > 0.5 ? "test" : 5,
    };
}

If you plug this into TS, you'll get an error, because the value being returned is of type { data: string | number; }, not { data: string; } | { data: number; }.

That type is assignable to Result<string | number>

function getResult2(): Result<string | number> {
    // This is valid
    return {
        data: Math.random() ? "test" : 5,
    };
}

Now, this highlights a difference between how TS sees these types, but doesn't necessarily explain why the top-level type returned by an async can't be an intersection between two Promise<T> types. Afraid I don't have a thorough answer there.

  • Related