#How to get the return type of a generic Higher Order Function?

17 messages · Page 1 of 1 (latest)

arctic dove
#

You need to make example also generic, and pass the generic to secureAction.

#
async function example<T extends ...>(action: () => ReturnType<typeof secureAction<T>>) {
    // ...
}
arctic dove
#

The same constraint as secureAction so you can pass to it.

arctic dove
#

Just copy the generic from secureAction.

#

<Fn extends (...params: any[]) => any>

arctic dove
#

Why is execute using a new Promise?

#

That doesn't answer why you need a new Promise.

#

new Promise is only necessary if you want to turn callback style API into promise style, eg like what you did with setTimeout (because that's a callback style API)

#

But anyways that's irrelevant to your original question, you can fix execute by doing:

async function execute<T>(action: () => Promise<T | { reauthRequired: boolean }>) {
    const response = await action()

    if (response && typeof response === 'object' && 'reauthRequired' in response) {
        // ...
        return
    }

    return response
}
#

The guard clause gets a bit more complicated because you are not sure if action always returns an object, if you are fine with limiting that though, you can also do:

async function execute<T extends object>(action: () => Promise<T | { reauthRequired: boolean }>) {
    const response = await action()

    if ('reauthRequired' in response) {
        // ...
        return
    }

    return response
}
#

I mean, you are also hardcoding if ('reauthRequired' in response) { already.

#

Sure, change it to:

async function execute<T extends object>(action: ReturnType<typeof secureAction<() => T>>) {
#

It's still kind of fragile because it relies on secureAction returning certain shapes

#

If you want to improve it even more:

async function execute<T extends object>(
    action: () => ReturnType<ReturnType<typeof secureAction<() => T>>>,
) {
    // ...
}
#

Then just remove the generic constraint and add back in the null and object checks.

#

You can't resolve response as T inside the branch when the action failed and need reauth.

#
async function execute<T>(action: () => ReturnType<ReturnType<typeof secureAction<() => T>>>) {
    return new Promise<T | undefined>(async (resolve) => {
        const response = await action()

        if (response && typeof response === 'object' && 'reauthRequired' in response) {
            resolve(undefined)
        } else {
            resolve(response)
        }
    })
}