'Argument of type '() => Promise<string>' is not assignable to parameter of type 'Promise<string>'. ts(2345)

I'm defining a function that requires a asynchronous function as a parameter:

async function handle(def: Promise<string>) {
    // ...
    const data = await def;
    console.log(`data equals: ${data}`)
}

I can succesfully execute this by passing a promise.

handle(new Promise(async (res, rej) => {
    const data = await Promise.resolve("some data")
    if (data == "invalid")
        return rej("data is invalid")
    res(data)
}))

I need the inner-function to be async, since I need to perform awaits inside. However, I dislike the async in the promise and read online that its considered an anti-pattern.

I thought it was a better idea to get rid of the promise and use a basic async function:

handle(async () => {
    const data = await Promise.resolve("some data")
    if (data == "invalid")
        throw "data is invalid"
    return data
})

But the TS compiler raises the error:

Argument of type '() => Promise<string>' is not assignable to parameter of type 'Promise<string>'. ts(2345)

I thought that Promises and async functions are somewhat interchangable. I read that async functions always return a promise. Apperantly I am not interpreting this correctly, but I'm unsure what the error is telling me.

I hope the problem I am sketching is clear. It would be greatly appreciated if someone could clarify the error or give suggestions on how to implement this in the desired way. Big thanks!



Solution 1:[1]

In general, the time to use the Promise constructor in a situation like this is right when you call a callback-based function that you want to promisify. But here, it doesn't look like there's anything to promisify, so the Promise constructor doesn't really help.

If

I need the inner-function to be async, since I need to perform awaits inside.

You can have an immediately invoked async IIFE - yes, using an async callback for the Promise constructor wouldn't be safe, because it wouldn't handle errors.

handle((async () => {
    const data = await Promise.resolve("some data")
    if (data == "invalid")
        throw "data is invalid";
    return data
})())

The other option is to use .then - .then is interchangeable with await in many situations:

handle(
  Promise.resolve("some data")
    .then((data) => {
        if (data == "invalid")
            throw "data is invalid";
        return data;
    })
);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 CertainPerformance