Skip to content

Type inference fails with complex generic tuples #4136

@Ellisthion

Description

@Ellisthion

I've been trying to come up with a smarter type def for Angular's $q.all (https://docs.angularjs.org/api/ng/service/$q#all) which takes an array of promises and spits out a promise with an array of results as the value.

For reference, the current DefinitelyTyped implementation is:

    all(promises: IPromise<any>[]): IPromise<any[]>;

I'm attempting to rewrite it with tuples, like so:

    all<T1, T2, T3>([t1, t2, t3]: [IPromise<T1>, IPromise<T2>, IPromise<T3>]): IPromise<[T1, T2, T3]>;
    all<T1, T2>([t1, t2]: [IPromise<T1>, IPromise<T2>]): IPromise<[T1, T2]>;
    all<T1>([t1]: [IPromise<T1>]): IPromise<[T1]>;

Usage:

    // Fails type inference, causes error
    var a = $q.all([$q.when<string>(), $q.when<number>()]);

    // Explicit types work fine
    var b = $q.all<string, number>([$q.when<string>(), $q.when<number>()]);

    // Same generic type works fine
    var c = $q.all([$q.when<string>(), $q.when<string>()]);

Full example on Typescript playground: http://goo.gl/UOKBp7

Attempting to use this with multiple different implicit generic types (example a) causes this error:

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

As far as I can tell, the Typescript compiler should (ideally) be able to infer this fine. The error seems wrong: 'number' shouldn't be a candidate for T1 at all.

Metadata

Metadata

Assignees

Labels

In DiscussionNot yet reached consensusSuggestionAn idea for TypeScript

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions