@@ -7429,7 +7429,7 @@ namespace ts {
7429
7429
7430
7430
// Add the given types to the given type set. Order is preserved, duplicates are removed,
7431
7431
// and nested types of the given kind are flattened into the set.
7432
- function addTypesToUnion(typeSet: TypeSet, types: Type[] ) {
7432
+ function addTypesToUnion(typeSet: TypeSet, types: ReadonlyArray< Type> ) {
7433
7433
for (const type of types) {
7434
7434
addTypeToUnion(typeSet, type);
7435
7435
}
@@ -7504,7 +7504,7 @@ namespace ts {
7504
7504
// expression constructs such as array literals and the || and ?: operators). Named types can
7505
7505
// circularly reference themselves and therefore cannot be subtype reduced during their declaration.
7506
7506
// For example, "type Item = string | (() => Item" is a named type that circularly references itself.
7507
- function getUnionType(types: Type[] , subtypeReduction?: boolean, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type {
7507
+ function getUnionType(types: ReadonlyArray< Type> , subtypeReduction?: boolean, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type {
7508
7508
if (types.length === 0) {
7509
7509
return neverType;
7510
7510
}
@@ -10434,11 +10434,6 @@ namespace ts {
10434
10434
return symbol;
10435
10435
}
10436
10436
10437
- function createCombinedSymbolWithType(sources: ReadonlyArray<Symbol>, type: Type): Symbol {
10438
- // This function is currently only used for erroneous overloads, so it's good enough to just use the first source.
10439
- return createSymbolWithType(first(sources), type);
10440
- }
10441
-
10442
10437
function transformTypeOfMembers(type: Type, f: (propertyType: Type) => Type) {
10443
10438
const members = createSymbolTable();
10444
10439
for (const property of getPropertiesOfObjectType(type)) {
@@ -16526,49 +16521,22 @@ namespace ts {
16526
16521
hasCandidatesOutArray: boolean,
16527
16522
): Signature {
16528
16523
Debug.assert(candidates.length > 0); // Else should not have called this.
16529
-
16530
16524
// Normally we will combine overloads. Skip this if they have type parameters since that's hard to combine.
16531
16525
// Don't do this if there is a `candidatesOutArray`,
16532
16526
// because then we want the chosen best candidate to be one of the overloads, not a combination.
16533
- if (!hasCandidatesOutArray && candidates.length > 1 && !candidates.some(c => !!c.typeParameters)) {
16534
- return createUnionOfSignaturesForOverloadFailure(candidates);
16535
- }
16536
-
16537
- // Pick the longest signature. This way we can get a contextual type for cases like:
16538
- // declare function f(a: { xa: number; xb: number; }, b: number);
16539
- // f({ |
16540
- // Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like:
16541
- // declare function f<T>(k: keyof T);
16542
- // f<Foo>("
16543
- const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args.length : apparentArgumentCount);
16544
- const candidate = candidates[bestIndex];
16545
-
16546
- const { typeParameters } = candidate;
16547
- if (typeParameters && callLikeExpressionMayHaveTypeArguments(node) && node.typeArguments) {
16548
- const typeArguments = node.typeArguments.map(getTypeOfNode);
16549
- while (typeArguments.length > typeParameters.length) {
16550
- typeArguments.pop();
16551
- }
16552
- while (typeArguments.length < typeParameters.length) {
16553
- typeArguments.push(getDefaultTypeArgumentType(isInJavaScriptFile(node)));
16554
- }
16555
-
16556
- const instantiated = createSignatureInstantiation(candidate, typeArguments);
16557
- candidates[bestIndex] = instantiated;
16558
- return instantiated;
16559
- }
16560
-
16561
- return candidate;
16527
+ return hasCandidatesOutArray || candidates.length === 1 || candidates.some(c => !!c.typeParameters)
16528
+ ? pickLongestCandidateSignature(node, candidates, args)
16529
+ : createUnionOfSignaturesForOverloadFailure(candidates);
16562
16530
}
16563
16531
16564
16532
function createUnionOfSignaturesForOverloadFailure(candidates: ReadonlyArray<Signature>): Signature {
16565
16533
const thisParameters = mapDefined(candidates, c => c.thisParameter);
16566
16534
let thisParameter: Symbol | undefined;
16567
16535
if (thisParameters.length) {
16568
- thisParameter = createCombinedSymbolWithType (thisParameters, getUnionType( thisParameters.map(getTypeOfParameter), /*subtypeReduction*/ true ));
16536
+ thisParameter = createCombinedSymbolFromTypes (thisParameters, thisParameters.map(getTypeOfParameter));
16569
16537
}
16570
16538
16571
- const { min: minArgumentCount, max: maxNonRestParam } = minAndMax(candidates, getNumNonRestParameters);
16539
+ const { min: minArgumentCount, max: maxNonRestParam } = minAndMax(candidates, getNumNonRestParameters);
16572
16540
const hasRestParameter = candidates.some(c => c.hasRestParameter);
16573
16541
const hasLiteralTypes = candidates.some(c => c.hasLiteralTypes);
16574
16542
const parameters: ts.Symbol[] = [];
@@ -16577,15 +16545,14 @@ namespace ts {
16577
16545
i < parameters.length - 1 ? parameters[i] : last(parameters) :
16578
16546
i < parameters.length ? parameters[i] : undefined);
16579
16547
Debug.assert(symbols.length !== 0);
16580
- const types = mapDefined(candidates, candidate => tryGetTypeAtPosition(candidate, i));
16581
- parameters.push(createCombinedSymbolWithType(symbols, getUnionType(types, /*subtypeReduction*/ true)));
16548
+ parameters.push(createCombinedSymbolFromTypes(symbols, mapDefined(candidates, candidate => tryGetTypeAtPosition(candidate, i))));
16582
16549
}
16583
16550
16584
16551
if (hasRestParameter) {
16585
16552
const symbols = mapDefined(candidates, c => c.hasRestParameter ? last(c.parameters) : undefined);
16586
16553
Debug.assert(symbols.length !== 0);
16587
16554
const type = createArrayType(getUnionType(mapDefined(candidates, tryGetRestTypeOfSignature), /*subtypeReduction*/ true));
16588
- parameters.push(createCombinedSymbolWithType (symbols, type));
16555
+ parameters.push(createCombinedSymbolForOverloadFailure (symbols, type));
16589
16556
}
16590
16557
16591
16558
return createSignature(
@@ -16600,7 +16567,44 @@ namespace ts {
16600
16567
hasLiteralTypes);
16601
16568
}
16602
16569
16603
- function getLongestCandidateIndex(candidates: Signature[], argsCount: number): number {
16570
+ function createCombinedSymbolFromTypes(sources: ReadonlyArray<Symbol>, types: ReadonlyArray<Type>): Symbol {
16571
+ return createCombinedSymbolForOverloadFailure(sources, getUnionType(types, /*subtypeReduction*/ true));
16572
+ }
16573
+
16574
+ function createCombinedSymbolForOverloadFailure(sources: ReadonlyArray<Symbol>, type: Type): Symbol {
16575
+ // This function is currently only used for erroneous overloads, so it's good enough to just use the first source.
16576
+ return createSymbolWithType(first(sources), type);
16577
+ }
16578
+
16579
+ function pickLongestCandidateSignature(node: CallLikeExpression, candidates: Signature[], args: ReadonlyArray<Expression>): Signature {
16580
+ // Pick the longest signature. This way we can get a contextual type for cases like:
16581
+ // declare function f(a: { xa: number; xb: number; }, b: number);
16582
+ // f({ |
16583
+ // Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like:
16584
+ // declare function f<T>(k: keyof T);
16585
+ // f<Foo>("
16586
+ const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args.length : apparentArgumentCount);
16587
+ const candidate = candidates[bestIndex];
16588
+
16589
+ const { typeParameters } = candidate;
16590
+ if (typeParameters && callLikeExpressionMayHaveTypeArguments(node) && node.typeArguments) {
16591
+ const typeArguments = node.typeArguments.map(getTypeOfNode);
16592
+ while (typeArguments.length > typeParameters.length) {
16593
+ typeArguments.pop();
16594
+ }
16595
+ while (typeArguments.length < typeParameters.length) {
16596
+ typeArguments.push(getDefaultTypeArgumentType(isInJavaScriptFile(node)));
16597
+ }
16598
+
16599
+ const instantiated = createSignatureInstantiation(candidate, typeArguments);
16600
+ candidates[bestIndex] = instantiated;
16601
+ return instantiated;
16602
+ }
16603
+
16604
+ return candidate;
16605
+ }
16606
+
16607
+ function getLongestCandidateIndex(candidates: ReadonlyArray<Signature>, argsCount: number): number {
16604
16608
let maxParamsIndex = -1;
16605
16609
let maxParams = -1;
16606
16610
0 commit comments