15

I would like to use the return type of a function to type an item on an interface like so:

const returnsPromise = async (): Promise<string> => {
  return Promise.resolve('I want the string type and not a Promise')
}

interface Myinterface {
  message: ReturnType<typeof returnsPromise>
}

However, message is of type Promise instead of string. Can one get the type a promise ought to resolve with?

Chubi Best
  • 338
  • 2
  • 11
  • 1
    I'm not sure I actually understand your question, but you can extract the type out of a Promise like so: `type GetFromPromise = T extends Promise ? U : never`. Calling that type works like so: `type IsString = GetFromPromise>`. If that's what your looking for, again it's not clear. – Jared Smith Dec 18 '21 at 19:53
  • Does this answer your question? [How to unwrap the type of a Promise?](https://stackoverflow.com/questions/48011353/how-to-unwrap-the-type-of-a-promise) – Gerrit0 Dec 19 '21 at 00:01

1 Answers1

18

TypeScript 4.5 introduced the Awaited<T> type, which evaluates to the type you get if you await a value of type T. So you could write:

interface Myinterface {
  message: Awaited<ReturnType<typeof returnsPromise>>;
  // (property) Myinterface.message: string
}

If you don't have TypeScript 4.5 yet, you can always "un-Promise" a type yourself with conditional type inference:

type Unpromise<T> = T extends Promise<infer U> ? U : never;

interface Myinterface {
  message: Unpromise<ReturnType<typeof returnsPromise>>;
  // (property) Myinterface.message: string
}

They both produce string when you pass in Promise<string>. For more complicated types like nested Promises, they produce different results:

type APPs = Awaited<Promise<Promise<string>>>; // type APPs = string
type UPPs = Unpromise<Promise<Promise<string>>>; // type UPPs = Promise<string>

So it depends on your use cases whether you need to calculate "what a promise resolves with" recursively or not.

Playground link to code

jcalz
  • 264,269
  • 27
  • 359
  • 360