Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Promise.all sometimes infers incorrect types #52601

Open
JavaScriptBach opened this issue Feb 4, 2023 · 5 comments
Open

Promise.all sometimes infers incorrect types #52601

JavaScriptBach opened this issue Feb 4, 2023 · 5 comments
Labels
Needs More Info The issue still hasn't been fully clarified

Comments

@JavaScriptBach
Copy link

JavaScriptBach commented Feb 4, 2023

Bug Report

πŸ”Ž Search Terms

Promise.all, Awaited

πŸ•— Version & Regression Information

4.9.5

⏯ Playground Link

I couldn't repro this bug in the playground.

Please see this test repo instead.

πŸ’» Code

Multiple files are needed to repro this bug. See the test repo. The relevant error is:

export async function testPromiseAll(docs: string[]) {
  const requests = docs.map(async doc => fetch("/doc"));
  const responses = await Promise.all(requests);
  for (const res of responses) {
    await res.blob(); // Property 'blob' does not exist on type 'Promise<Response>'.
  }
}

πŸ™ Actual behavior

Code fails to build with:

Property 'blob' does not exist on type 'Promise<Response>'.

This is because the return type of Promise.all() becomes a Promise<Array<Promise<Response>>> instead of a Promise<Array<Response>>.

πŸ™‚ Expected behavior

Code typechecks.

@JavaScriptBach
Copy link
Author

Possibly also related to #51993

@RyanCavanaugh RyanCavanaugh added the Needs More Info The issue still hasn't been fully clarified label Feb 4, 2023
@RyanCavanaugh
Copy link
Member

We'd need some way to reproduce this

@ritschwumm
Copy link

ritschwumm commented Feb 4, 2023

no idea whether this is helpful or even related:

in the past (probably 4.7.x or even 4.6.x) i had a vaguely similar problem without Promise.all involved at all, just some large-ish function call expression being awaited, and tsc complaining it could not assign to the variable because the types were mismatched.

the interesting part was, that while

const xxx:SomeType = await something();

failed to compile,

const xxx = await something();
const yyy:SomeType = xxx;

worked perfectly fine, and at least in vscode the popup on xxx did show the expected type SomeType.
additionally,

const xxx:Promise<SomeType> = something();

worked fine, too.

to me the whole thing felt like the mechanism behind await did something strange after looking into the expected type derived from the variable's type annotation, but as i have no idea how the actual implementation works, my assumption is probably completely wrong :)

@JavaScriptBach
Copy link
Author

I think I found the issue. The problem is there are two overloads of Promise.all(), defined in separate files:

https://github.com/microsoft/TypeScript/blob/main/lib/lib.es2015.iterable.d.ts#L227
https://github.com/microsoft/TypeScript/blob/main/lib/lib.es2015.promise.d.ts#L41

The former is intended for arrays and the latter for tuples, but arrays are sometimes getting matched with the tuple overload. Moving the definitions into the same file and declaring the array one first solved my issue.

(Per Typescript docs, TypeScript chooses the first matching overload, but I'm not sure what this behavior is if the overloads are specified in separate files. Probably it's undefined?)

@JavaScriptBach
Copy link
Author

@RyanCavanaugh I've attached a repro to the issue. Hope you or someone else on the team could take a look. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs More Info The issue still hasn't been fully clarified
Projects
None yet
Development

No branches or pull requests

3 participants