Dynalon
Dynalon

Reputation: 6814

Wrap a function whose return value is Promise<T> | undefined to always return Promise and maintain typing

I have a function callback<T> whose return value is either Promise<T> or undefined. Now I want to create a wrapping function that will execute the function and always returns a Promise - in case the callback function returned undefined, the Promise should resolve with undefined.

The code isn't the problem, but maintaining type inference in Typescript. How would the function signature have to look so that the typing is maintained?

(non-working) example:

function wrap<T>(callback: () => Promise<T> | undefined): Promise<T> | Promise<undefined>

// inferred signature should be Promise<undefined>
const a = wrap(() => undefined)

// inferred signature should be Promise<number>
const b = wrap(() => Promise.resolve(5))

Upvotes: 1

Views: 552

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074365

My first thought is a function overload:

function wrap<T>(callback: () => Promise<T>): Promise<T>;
function wrap(callback: () => undefined): Promise<undefined>;
function wrap<T>(callback: () => any): Promise<T | undefined> {
    const result = callback();
    if (typeof result === "undefined") {
        return Promise.resolve(undefined);
    }
    return result;
}

Live on the playground

That can also be expressed in a type if that's useful:

type Wrapper = {
    <T>(callback: () => Promise<T>): Promise<T>;
    (callback: () => undefined): Promise<undefined>;
}

const wrap: Wrapper = (callback: () => any) {
    const result = callback();
    if (typeof result === "undefined") {
        return Promise.resolve(undefined);
    }
    return result;
};

On the playground

Upvotes: 2

Related Questions