Skip to content

es6-promise Promise.all error #5935

Closed
Closed

Description

When I use the es6-promise type definitions, given this code:

Promise.all([
    Promise.resolve('foo'),
    Promise.resolve(['bar'])
]);

I get the following error:

The type argument for type parameter 'R' cannot be inferred from the usage. Consider specifying the type arguments explicitly.
Type argument candidate 'string' is not a valid type argument because it is not a supertype of candidate 'string[]'.

Can you explain why this is? I don't understand the error.

Activity

  1. blakeembrey commented on Dec 4, 2015

    @blakeembrey
    Contributor

    If you're using https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/es6-promise/es6-promise.d.ts#L59, I found it's because those two items in the array resolve to different promise types. Try specifying it explicitly, usually works for me:

    Promise.all<[string, string[]]>([
        Promise.resolve('foo'),
        Promise.resolve(['bar'])
    ])
    

    Edit: Wrong syntax, but Promise.all<Promise<string> | Promise<string[]>> works.

  2. OliverJAsh commented on Dec 4, 2015

    @OliverJAsh
    ContributorAuthor

    Can you help me understand why this can't be inferred?

    On Fri, 4 Dec 2015, 18:01 Blake Embrey notifications@github.com wrote:

    If you're using
    https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/es6-promise/es6-promise.d.ts#L59,
    I found it's because those two items in the array resolve to different
    promise types. Try specifying it explicitly, usually works for me:

    Promise.all<[string, string[]]>([
    Promise.resolve('foo'),
    Promise.resolve(['bar'])
    ])

    —
    Reply to this email directly or view it on GitHub
    #5935 (comment)
    .

  3. blakeembrey commented on Dec 4, 2015

    @blakeembrey
    Contributor

    Can you help me understand why this can't be inferred?

    I'm not the best person for that, I'll leave it for the TypeScript team to answer.

  4. OliverJAsh commented on Dec 4, 2015

    @OliverJAsh
    ContributorAuthor

    Blake Embrey (@blakeembrey) I believe this is the correct syntax:

    Promise.all<string | string[]>([
        Promise.resolve('foo'),
        Promise.resolve(['bar'])
    ])
    

    If you try adding .then((x) => x) to the end of your assertion, you get errors.

  5. blakeembrey commented on Dec 4, 2015

    @blakeembrey
    Contributor

    Not causing issues for me. (link) What version (of TypeScript) are you using?

  6. OliverJAsh commented on Dec 4, 2015

    @OliverJAsh
    ContributorAuthor

    Yes, that works. Sorry, I was trying to say the type assertion you provided didn't work (Promise.all<Promise<string> | Promise<string[]>>).

    This is what I have ended up with:

    Promise.all<string | number>([
        Promise.resolve('1'),
        Promise.resolve(1)
    ])
        .then(([x, y]: [string, number]) => {
            x
            y
        })

    I provide the type of the tuple in the then callback function so I can continue to use the type checker. If I did the following:

    Promise.all<string | number>([
        Promise.resolve('1'),
        Promise.resolve(1)
    ])
        .then(([x, y]) => {
            x
            y
        })

    … then the compiler wouldn't know if x is a string or number.

    This is a bit of a PITA. I'm trying to understand if it's possible to write a better type definition for Promise.all so assertions are not needed?

  7. blakeembrey commented on Dec 4, 2015

    @blakeembrey
    Contributor

    Right, I understand. I don't think it's currently possible to do that since there's no way to express the generic variadically, but this discussion might relate to the proposal in #5453. The TypeScript team should chime in if there's a better approach at the moment, but I've done the same thing as you ended up with in the past.

  8. mhegazy commented on Dec 7, 2015

    @mhegazy
    Contributor

    untill #5453 is in, we can add a punch of overloads (say 2-10) to make Promise.all more user friendly. something like:

    interface PromiseConstructor {
        all<T1, T2>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>]): Promise<[T1, T2]>;
        all<T1, T2, T3>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>]): Promise<[T1, T2, T3]>;
        all<T1, T2, T3, T4>(values: [T1 | PromiseLike<T1>, T2 | PromiseLike<T2>, T3 | PromiseLike<T3>, T4 | PromiseLike<T4>]): Promise<[T1, T2, T3, T4]>;
        ..............
    }

    Nathan Shively-Sanders (@sandersn) thoughts?

  9. sandersn commented on Dec 7, 2015

    @sandersn
    Member

    Yes, multiple overloads is the accepted workaround until we have variadic generics from #5453.

    I put variadic kinds behind this-types functions because this-types don't have a simple (albeit verbose) workaround. So I think it's worthwhile to add the overloads now until variadic kinds are in. I'll link the PR when it's done.

  10. added
    BugA bug in TypeScript
    Domain: lib.d.tsThe issue relates to the different libraries shipped with TypeScript
    and removed
    QuestionAn issue which isn't directly actionable in code
    on Dec 7, 2015
  11. sandersn commented on Dec 7, 2015

    @sandersn
    Member

    Here's the PR: #5973.

  12. locked and limited conversation to collaborators on Jun 19, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugA bug in TypeScriptDomain: lib.d.tsThe issue relates to the different libraries shipped with TypeScriptFixedA PR has been merged for this issueHelp WantedYou can do this

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions