简体   繁体   中英

Conditional return type based on argument type in Typescript

I want to define a generic function type named Callbackify in Typescript that does the following things:

  • If the given argument is undefined, return a promise of given generic type E
  • If the given argument is a callback function, return void

I want to use it as a return type for this callbackify function:

function callbackify<E>(executor: () => Promise<E>):  Callbackify<E> {
   // omitted implementation
}

A few use cases of the function would be:

const fn = callbackify(() => Promise.resolve(4));

// given a callback function as an argument, so should return void
let returnValue = fn((err, value) => { console.log(err, value) })
typeof returnValue // void

//given no argument, so should return Promise<number>
let returnValue = fn()
typeof returnValue // Promise<number>

I have tried the following way but it does not seem to work as expected (it always returns void)

export type CallbackFunction<T> = (error: Error | null, value?: T) => void;
export type Callbackify<T extends CallbackFunction<E>> = (done?: T) => T extends undefined | null ? Promise<E> : void;

I would just use overloads. Overloads are a better match for what you are trying to do:


export type CallbackFunction<T> = (error: Error | null, value?: T) => void;
export type Callbackify<E> = {
    (done: CallbackFunction<E>): void;
    (): Promise<E>;
}

function callbackify<E>(executor: () => Promise<E>): Callbackify<E> { // Explicit return type not really necesarry 
    function callbackified(done: CallbackFunction<E>): void;
    function callbackified(): Promise<E>;
    function callbackified(done?: CallbackFunction<E>): Promise<E> | void {
        return null!
    }
    return callbackified;
}


Playground Link

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM