Skip to content

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

Closed
@bgmort

Description

@bgmort

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    BugA bug in TypeScriptDomain: lib.d.tsThe issue relates to the different libraries shipped with TypeScriptHelp WantedYou can do this

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions