microsoft / microsoft/TypeScript

async function drops `Awaited<Type>`

Open
#56,083 0 comments 0 reactions 1 assignee View on GitHub

@rbuckton is already working on this.

Since Oct 12, 2023.

Needs Investigation
Dominant language
Go
Stars
111k
Forks
14.3k
Avg merge
1d 19h
Merged PRs (30d)
117

Description

🔎 Search Terms

async function drops Awaited
Awaited swallowed in async
Awaited removed

🕗 Version & Regression Information
  • This is the behavior in every TS version I tried, started occurring since TS v 4.5.5 when the Awaited was introduced.
⏯ Playground Link

https://www.typescriptlang.org/play?ts=4.5.5#code/PTAEGcEsHMDsEMAuBXATgU3KA9gM1IgBbqi7KwDGik2sW8GoF2ADpOgCamrYC2oABR69I4dADpU8CugBQsspWq1QUmQH1IHdLGqIAnuuwBrADwAVUOgAeiHRywZ4HWgBt9ocsdjYA7rABtAF1QAB9QYIA+AApQADd4V2RMAC5QcwBKNKE+UXRTAEFfeEg7DgsA2GReACN0VCDIyNAAb1lQDtV0FFRYQWE8yWl0aISkzAyOkFAAeQBpABpQLR09D0UqGj7fbFRjLAArZHBEUkhYOQBfeQ3lPrV0dV8pFhZOTVh1eHB9SnUfRBGMyWGx2WAOLrONweLw+fzBMIRRqxMbJcBpTLZAZiQrFUqcCpVWr1RrNNqdJi0E6gb6-CgAdReb1QoAAvDSfpRQNFJqyye0KZ1mHRTg82TS8acciIxEMZKNEmiMgLBaBpsLqQ80kUSmVCdU6g1moL5ksiKICPo3sssDY3lROCrBRgevdhhSndcKeqqadaZRGfBXvU0jy2c1pXl9cSjYLzVgLQDZotQE7pr4SHb0FRLdaw3z+rkcTr8eVzJUDSSmksashTkQSAADEt6yKN0DFLAcHjBjhLZmEIPgAD88gpLrQfX9DKZ9R5abA9R4qBSC-SVpIAHJIzjy0TDY1NzbQEnvlA4PAaq4SIhsLmtzv8i2CXvK0bIpvxGvzBvQJvXzGQRHom2B+uA54IFeN53gY1qbs+ZYVoBH7iNEABMADMaFocqlxAA

💻 Code
// signatures of the functions are copied from Promise.race

function race_identity_ok<T extends readonly unknown[] | []>( values: T): Promise<Awaited<T[number]>> {
    return Promise.race(values)  // OK, identity function works just fine
}

function race_wrapped_in_async_not_ok<T extends readonly unknown[] | []>( values: T): Promise<Awaited<T[number]>> {
    const asyncWrapper = async () => {
        const race = await Promise.race(values)
        // const race: Awaited<T[number]>      OK, this type is expected
        return race    
    }
    // const asyncWrapper: () => Promise<T[number]>     this is not OK, 
    // we expect type () => Promise<Awaited<T[number]>>, but the `Awaited<>` was dropped, perhaps?

    return asyncWrapper()
    // error:
    // Type 'Promise<T[number]>' is not assignable to type 'Promise<Awaited<T[number]>>'.
    // Type 'T[number]' is not assignable to type 'Awaited<T[number]>'.(2322)
}```


### 🙁 Actual behavior

The `Awaited<Type>` is dropped from the return type of the function `asyncWrapper`, but it should not be (at least as I can tell).


### 🙂 Expected behavior

The `Awaited` should not be dropped.
I believe so because I assume the `Awaited` in the `Promise.race` signature is of crucial importance, as it denotes that if type `T` is a thenable (or `PromiseLike`, if you like), it is unwrapped in the return type.
Wrapping the `Promise.race` in `async` function (`asyncWrapper`) looses the unwrapping semantics, in my opinion.



### Additional information about the issue

The issue might seem artificial, however, this is the minimalist example I came up with. In our codebase, the issue is convoluted because we replace `PromiseLike` with [CancellablePromise](https://github.com/srmagura/real-cancellable-promise). We need the async function wrapper to correctly deduce return type (and keep the `Awaited`), so that the return type of `Promise.race` is perserved when fed through the [buildCancellablePromise](https://github.com/srmagura/real-cancellable-promise#combine-multiple-api-calls-into-a-single-async-flow).

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.