Skip to content

Inference to generic overloaded construct signatures fails #35641

Closed
@rbuckton

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

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