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

Tuple defined with as const can't be passed to Promise.all #31179

Closed
bgmort opened this issue Apr 30, 2019 · 2 comments · Fixed by #33057
Closed

Tuple defined with as const can't be passed to Promise.all #31179

bgmort opened this issue Apr 30, 2019 · 2 comments · Fixed by #33057
Labels
Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript Help Wanted You can do this
Milestone

Comments

@bgmort
Copy link

bgmort commented Apr 30, 2019

TypeScript Version:
3.4.3
3.4.5
3.5.0-dev.20190430

Search Terms:
Promise.all, array, tuple, as const

Code

// requires `--lib es2017` to run

const p1 = Promise.resolve(1);
const p2 = Promise.resolve('two');
const p3 = Promise.resolve(true);

(async () => {
    // works fine
    // let [v1, v2, v3] = await Promise.all([p1, p2, p3]);

    // also fine
    // const promises = [p1, p2, p3] as [typeof p1, typeof p2, typeof p3];

    // not fine
    const promises = [p1, p2, p3] as const;

    let [v1, v2, v3] = await Promise.all(promises);

    // quick type test
    v1.toExponential();
    v2.toUpperCase();
    let b: boolean = v3;
})();

Expected behavior:
Promise.all accepts a tuple of Promise objects. Code compiles.

Actual behavior:
An array of promises defined using as const can't be passed to Promise.all. With the latest ts build, I get the following compilation error:

bug.ts:15:42 - error TS2345: Argument of type 'readonly [Promise<number>, Promise<string>, Promise<boolean>]' is not assignable to parameter of type 'Iterable<number | PromiseLike<number>>'.
  Types of property '[Symbol.iterator]' are incompatible.
    Type '() => IterableIterator<Promise<number> | Promise<string> | Promise<boolean>>' is not assignable to type '() => Iterator<number | PromiseLike<number>>'.
      Type 'IterableIterator<Promise<number> | Promise<string> | Promise<boolean>>' is not assignable to type 'Iterator<number | PromiseLike<number>>'.
        Types of property 'next' are incompatible.
          Type '(value?: any) => IteratorResult<Promise<number> | Promise<string> | Promise<boolean>>' is not assignable to type '(value?: any) => IteratorResult<number | PromiseLike<number>>'.
            Type 'IteratorResult<Promise<number> | Promise<string> | Promise<boolean>>' is not assignable to type 'IteratorResult<number | PromiseLike<number>>'.
              Type 'Promise<number> | Promise<string> | Promise<boolean>' is not assignable to type 'number | PromiseLike<number>'.
                Type 'Promise<string>' is not assignable to type 'number | PromiseLike<number>'.
                  Type 'Promise<string>' is not assignable to type 'PromiseLike<number>'.
                    Types of property 'then' are incompatible.
                      Type '<TResult1 = string, TResult2 = never>(onfulfilled?: (value: string) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => Promise<TResult1 | TResult2>' is not assignable to type '<TResult1 = number, TResult2 = never>(onfulfilled?: (value: number) => TResult1 | PromiseLike<TResult1>, onrejected?: (reason: any) => TResult2 | PromiseLike<TResult2>) => PromiseLike<TResult1 | TResult2>'.
                        Types of parameters 'onfulfilled' and 'onfulfilled' are incompatible.
                          Types of parameters 'value' and 'value' are incompatible.
                            Type 'string' is not assignable to type 'number'.

15     let [v1, v2, v3] = await Promise.all(promises);
                                            ~~~~~~~~


Found 1 error.

Playground Link:
https://www.typescriptlang.org/play/#src=function%20promiseValue%3CT%3E(value%3A%20T)%20%7B%0D%0A%20%20%20%20return%20Promise.resolve(value)%3B%0D%0A%7D%0D%0A%0D%0Aconst%20p1%20%3D%20Promise.resolve(1)%3B%0D%0Aconst%20p2%20%3D%20Promise.resolve('two')%3B%0D%0Aconst%20p3%20%3D%20Promise.resolve(true)%3B%0D%0A%0D%0A(async%20()%20%3D%3E%20%7B%0D%0A%20%20%20%20%2F%2F%20works%20fine%0D%0A%20%20%20%20%2F%2F%20let%20%5Bv1%2C%20v2%2C%20v3%5D%20%3D%20await%20Promise.all(%5Bp1%2C%20p2%2C%20p3%5D)%3B%0D%0A%0D%0A%20%20%20%20%2F%2F%20also%20fine%0D%0A%20%20%20%20%2F%2F%20const%20promises%20%3D%20%5Bp1%2C%20p2%2C%20p3%5D%20as%20%5Btypeof%20p1%2C%20typeof%20p2%2C%20typeof%20p3%5D%3B%0D%0A%0D%0A%20%20%20%20%2F%2F%20not%20fine%0D%0A%20%20%20%20const%20promises%20%3D%20%5Bp1%2C%20p2%2C%20p3%5D%20as%20const%3B%0D%0A%0D%0A%20%20%20%20let%20%5Bv1%2C%20v2%2C%20v3%5D%20%3D%20await%20Promise.all(promises)%3B%0D%0A%0D%0A%20%20%20%20%2F%2F%20quick%20type%20test%0D%0A%20%20%20%20v1.toExponential()%3B%0D%0A%20%20%20%20v2.toUpperCase()%3B%0D%0A%20%20%20%20let%20b%3A%20boolean%20%3D%20v3%3B%0D%0A%7D)()%3B%0D%0A%0D%0A

@nmain
Copy link

nmain commented May 1, 2019

The tuple overloads of Promise.all all take writable tuples, so the only matching overload when you pass a readonly tuple is all<TAll>(values: Iterable<TAll | PromiseLike<TAll>>): Promise<TAll[]>;, which requires a single TAll parameter. The lib definitions should probably be changed.

@weswigham weswigham added Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript Help Wanted You can do this labels May 3, 2019
@bgmort
Copy link
Author

bgmort commented May 6, 2019

I'd be happy to take a stab at it this week.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Domain: lib.d.ts The issue relates to the different libraries shipped with TypeScript Help Wanted You can do this
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants