TypeScript: ReturnType for async functions

Since the introduction of the ReturnType in TypeScript 2.8, we can build up types based on the results of functions, without mentioning the types explicitly:

function createContext<T extends () => any>(configProvider: T): { config: ReturnType<T> } {
    return {
        config: configProvider(),
    }
}

function apiConfig() {
    return {
        endpoint: 'https://www.example.com'
    }
}

/**
 * context has type `{ config: { endpoint: string; }; }`
 */
const context =  createContext(apiConfig);

Playground

Now that async functions are becoming more prevalent in the code I work with, I have been wondering whether a similar helper can be employed to get the type of a successfully resolved Promise.

As a first building block I wrote a type to extract the Promise's resolved type:

type PromiseResolvedType<T> = T extends Promise<infer R> ? R : never;

// Type is currently Promise<number>
const promise = Promise.resolve(3);

// value has type `number`, will stay in sync with type of `promise` variable
let comparisionValue: PromiseResolvedType<typeof promise> = 5;

promise.then(value => console.log(`Value equal to comparison?`, value === comparisionValue));

Playground

That works nicely to limit our comparision value to the same type as the Promise instance might eventually resolve to. That way we can ensure consistency. If the types were not matching, the comparison will definitely fail, so we get faster feedback by moving that first check to the compile time of the program.

The final step is now to return the ReturnType with the PromiseResolvedType to access the success value of a Promise returned by a function:

type PromiseResolvedType<T> = T extends Promise<infer R> ? R : never;
type ReturnedPromiseResolvedType<T> = PromiseResolvedType<ReturnType<T>>
// or flattened: type ReturnedPromiseResolvedType<T> = T extends (...args: any[]) => Promise<infer R> ? R : never;

async function random(): Promise<number> {
  return Math.random();
}

type RandomFuncResolvedType = ReturnedPromiseResolvedType<typeof random>; // number

Playground