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

Inference to generic overloaded construct signatures fails #35641

Closed
rbuckton opened this issue Dec 12, 2019 · 2 comments
Closed

Inference to generic overloaded construct signatures fails #35641

rbuckton opened this issue Dec 12, 2019 · 2 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@rbuckton
Copy link
Member

rbuckton commented Dec 12, 2019

TypeScript Version: 3.8.0-dev.20191210 (nightly)

Search Terms: inference generic overload construct signature

Code

declare class MySet<T> {
    constructor(iterable?: Iterable<T> | null)
    // constructor(iterable?: readonly T[] | null);
    readonly size: number;
    add(value: T): this;
    clear(): void;
    delete(value: T): boolean;
    forEach(callbackfn: (value: T, value2: T, set: Set<T>) => void, thisArg?: any): void;
    has(value: T): boolean;
}

declare function collect<T, U>(it: Iterable<T>, collector: new (iterable: Iterable<T>) => U): U;

collect([1, 2, 3], Set); // expected: Set<number>, actual: Set<unknown>
collect([1, 2, 3], MySet); // expected: MySet<number>, actual: MySet<number>

Expected behavior:

The return type of the 1st call to collect should be Set<number>, similar to how the return type of the 2nd call to collect is MySet<number>

Actual behavior:

The return type of the 1st call to collect is Set<unknown>. This seems to be due to the combination of the following definitions:

// lib.es2015.collection.d.ts
interface SetConstructor {
    new <T = any>(values?: readonly T[] | null): Set<T>;
    readonly prototype: Set<any>;
}
declare var Set: SetConstructor;

// lib.es2015.iterable.d.ts
interface SetConstructor {
    new <T>(iterable?: Iterable<T> | null): Set<T>;
}

Commenting out the first construct signature for SetConstructor (in lib.es2015.collection.d.ts) produces the correct return type for collect. Likewise, uncommenting the similar constructor definition in MySet above results in collect producing the incorrect return type as well.

Playground Link: 🔗

Related Issues: #25917, #35636 (possibly related?)

@MartinJohns
Copy link
Contributor

Type inference in conditional types does not work with overloaded signatures:

When inferring from a type with multiple call signatures (such as the type of an overloaded function), inferences are made from the last signature (which, presumably, is the most permissive catch-all case). It is not possible to perform overload resolution based on a list of argument types.

@ChuckJonas
Copy link

I ran into something similar while messing around with variadic tuples, but I assume it's the same problem:

Playground Link

Although, I don't think this implementation contains conditional types...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

4 participants