Closed
Description
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: 🔗