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

pAll incorrectly infers type to unknown[] when pAll has nested promises (unless the function is async) #15

Open
gndelia opened this issue Dec 18, 2024 · 1 comment

Comments

@gndelia
Copy link

gndelia commented Dec 18, 2024

Unsure if this is a typescript problem, or something related to the definition of p-all's types

It seems that if the task passed to pAll uses .then internally, the api fails to infer the proper type of the result, unless the task is defined as async.

I am using pAll in a complex scenario, but a simplified code in which I was able to reproduce the bug is:

const numbers = [1, 2, 3]
pAll(
  numbers.map(
    n => () =>
      Promise.resolve().then(() => ({
        n,
      })),
  ),
).then(function (results) {
  results
})

If I hover on visual studio code, results is inferred as unknown[]

image

The proper inference should be { n: number } []

Workaround

If the task is defined as async, the results type is inferred correctly

const numbers = [1, 2, 3]
pAll(
  numbers.map(
    // async added here
    n => async () =>
      Promise.resolve().then(() => ({
        n,
      })),
  ),
).then(function (results) {
  results
})

The type is now correctly inferred

image

If I use an intermediate variable, it also works (without async)

const numbers = [1, 2]
const actions = numbers.map(
  n => () =>
    Promise.resolve().then(() => ({
      n,
    })),
)
pAll(
  actions,
).then(function (results) {
  console.log(results)
})

if I hover on VS code:

image

type is correctly inferred

Test that should pass

import {expectType} from 'tsd';
import pAll from './index.js';

const numbers1 = [1, 2]

// this passes
const result1 = await pAll(numbers1.map(
	n => async () =>
		Promise.resolve().then(() => ({
			n,
		}))), {concurrency: 2});

expectType<{ n: number }>(result1[0]);
expectType<{ n: number }>(result1[1]);

// this passes as well
import {expectType} from 'tsd';
import pAll from './index.js';

const numbers2 = [1, 2]

const actions2 = numbers.map(
	n => () =>
		Promise.resolve().then(() => ({
			n,
		})))

const result2 = await pAll(actions2, {concurrency: 2});

expectType<{ n: number }>(result2[0]);
expectType<{ n: number }>(result2[1]);


// this doesn't
const numbers3 = [1, 2]
const result3 = await pAll(numbers3.map(
	n => () =>
		Promise.resolve().then(() => ({
			n,
		}))), {concurrency: 2});

expectType<{ n: number }>(result3[0]);
expectType<{ n: number }>(result3[1]);
@sindresorhus
Copy link
Owner

I looked into this and could not find a workaround for p-all. This issue is likely a TypeScript limitation or bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants