Skip to content

Inference to generic overloaded construct signatures fails #35641

Description

@rbuckton

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?)

Activity

  1. MartinJohns commented on Dec 12, 2019

    @MartinJohns
    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.

  2. ChuckJonas commented on Aug 7, 2020

    @ChuckJonas

    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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Design LimitationConstraints of the existing architecture prevent this from being fixed

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions