@@ -7567,13 +7567,17 @@ namespace ts {
7567
7567
}
7568
7568
7569
7569
function getRestTypeOfSignature(signature: Signature): Type {
7570
+ return tryGetRestTypeOfSignature(signature) || anyType;
7571
+ }
7572
+
7573
+ function tryGetRestTypeOfSignature(signature: Signature): Type | undefined {
7570
7574
if (signature.hasRestParameter) {
7571
7575
const type = getTypeOfSymbol(last(signature.parameters));
7572
7576
if (getObjectFlags(type) & ObjectFlags.Reference && (<TypeReference>type).target === globalArrayType) {
7573
7577
return (<TypeReference>type).typeArguments![0];
7574
7578
}
7575
7579
}
7576
- return anyType ;
7580
+ return undefined ;
7577
7581
}
7578
7582
7579
7583
function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean): Signature {
@@ -18559,38 +18563,7 @@ namespace ts {
18559
18563
diagnostics.add(createDiagnosticForNode(node, fallbackError));
18560
18564
}
18561
18565
18562
- // No signature was applicable. We have already reported the errors for the invalid signature.
18563
- // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature.
18564
- // Pick the longest signature. This way we can get a contextual type for cases like:
18565
- // declare function f(a: { xa: number; xb: number; }, b: number);
18566
- // f({ |
18567
- // Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like:
18568
- // declare function f<T>(k: keyof T);
18569
- // f<Foo>("
18570
- if (!produceDiagnostics) {
18571
- Debug.assert(candidates.length > 0); // Else would have exited above.
18572
- const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args!.length : apparentArgumentCount);
18573
- const candidate = candidates[bestIndex];
18574
-
18575
- const { typeParameters } = candidate;
18576
- if (typeParameters && callLikeExpressionMayHaveTypeArguments(node) && node.typeArguments) {
18577
- const typeArguments = node.typeArguments.map(getTypeOfNode) as Type[]; // TODO: GH#18217
18578
- while (typeArguments.length > typeParameters.length) {
18579
- typeArguments.pop();
18580
- }
18581
- while (typeArguments.length < typeParameters.length) {
18582
- typeArguments.push(getDefaultTypeArgumentType(isInJavaScriptFile(node)));
18583
- }
18584
-
18585
- const instantiated = createSignatureInstantiation(candidate, typeArguments);
18586
- candidates[bestIndex] = instantiated;
18587
- return instantiated;
18588
- }
18589
-
18590
- return candidate;
18591
- }
18592
-
18593
- return resolveErrorCall(node);
18566
+ return produceDiagnostics || !args ? resolveErrorCall(node) : getCandidateForOverloadFailure(node, candidates, args, !!candidatesOutArray);
18594
18567
18595
18568
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>, signatureHelpTrailingComma = false) {
18596
18569
candidateForArgumentError = undefined;
@@ -18661,6 +18634,92 @@ namespace ts {
18661
18634
}
18662
18635
}
18663
18636
18637
+ // No signature was applicable. We have already reported the errors for the invalid signature.
18638
+ // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature.
18639
+ function getCandidateForOverloadFailure(
18640
+ node: CallLikeExpression,
18641
+ candidates: Signature[],
18642
+ args: ReadonlyArray<Expression>,
18643
+ hasCandidatesOutArray: boolean,
18644
+ ): Signature {
18645
+ Debug.assert(candidates.length > 0); // Else should not have called this.
18646
+ // Normally we will combine overloads. Skip this if they have type parameters since that's hard to combine.
18647
+ // Don't do this if there is a `candidatesOutArray`,
18648
+ // because then we want the chosen best candidate to be one of the overloads, not a combination.
18649
+ return hasCandidatesOutArray || candidates.length === 1 || candidates.some(c => !!c.typeParameters)
18650
+ ? pickLongestCandidateSignature(node, candidates, args)
18651
+ : createUnionOfSignaturesForOverloadFailure(candidates);
18652
+ }
18653
+
18654
+ function createUnionOfSignaturesForOverloadFailure(candidates: ReadonlyArray<Signature>): Signature {
18655
+ const thisParameters = mapDefined(candidates, c => c.thisParameter);
18656
+ let thisParameter: Symbol | undefined;
18657
+ if (thisParameters.length) {
18658
+ thisParameter = createCombinedSymbolFromTypes(thisParameters, thisParameters.map(getTypeOfParameter));
18659
+ }
18660
+ const { min: minArgumentCount, max: maxNonRestParam } = minAndMax(candidates, getNumNonRestParameters);
18661
+ const parameters: Symbol[] = [];
18662
+ for (let i = 0; i < maxNonRestParam; i++) {
18663
+ const symbols = mapDefined(candidates, ({ parameters, hasRestParameter }) => hasRestParameter ?
18664
+ i < parameters.length - 1 ? parameters[i] : last(parameters) :
18665
+ i < parameters.length ? parameters[i] : undefined);
18666
+ Debug.assert(symbols.length !== 0);
18667
+ parameters.push(createCombinedSymbolFromTypes(symbols, mapDefined(candidates, candidate => tryGetTypeAtPosition(candidate, i))));
18668
+ }
18669
+ const restParameterSymbols = mapDefined(candidates, c => c.hasRestParameter ? last(c.parameters) : undefined);
18670
+ const hasRestParameter = restParameterSymbols.length !== 0;
18671
+ if (hasRestParameter) {
18672
+ const type = createArrayType(getUnionType(mapDefined(candidates, tryGetRestTypeOfSignature), UnionReduction.Subtype));
18673
+ parameters.push(createCombinedSymbolForOverloadFailure(restParameterSymbols, type));
18674
+ }
18675
+ return createSignature(
18676
+ candidates[0].declaration,
18677
+ /*typeParameters*/ undefined, // Before calling this we tested for `!candidates.some(c => !!c.typeParameters)`.
18678
+ thisParameter,
18679
+ parameters,
18680
+ /*resolvedReturnType*/ getIntersectionType(candidates.map(getReturnTypeOfSignature)),
18681
+ /*typePredicate*/ undefined,
18682
+ minArgumentCount,
18683
+ hasRestParameter,
18684
+ /*hasLiteralTypes*/ candidates.some(c => c.hasLiteralTypes));
18685
+ }
18686
+
18687
+ function createCombinedSymbolFromTypes(sources: ReadonlyArray<Symbol>, types: Type[]): Symbol {
18688
+ return createCombinedSymbolForOverloadFailure(sources, getUnionType(types, UnionReduction.Subtype));
18689
+ }
18690
+
18691
+ function createCombinedSymbolForOverloadFailure(sources: ReadonlyArray<Symbol>, type: Type): Symbol {
18692
+ // This function is currently only used for erroneous overloads, so it's good enough to just use the first source.
18693
+ return createSymbolWithType(first(sources), type);
18694
+ }
18695
+
18696
+ function pickLongestCandidateSignature(node: CallLikeExpression, candidates: Signature[], args: ReadonlyArray<Expression>): Signature {
18697
+ // Pick the longest signature. This way we can get a contextual type for cases like:
18698
+ // declare function f(a: { xa: number; xb: number; }, b: number);
18699
+ // f({ |
18700
+ // Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like:
18701
+ // declare function f<T>(k: keyof T);
18702
+ // f<Foo>("
18703
+ const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args.length : apparentArgumentCount);
18704
+ const candidate = candidates[bestIndex];
18705
+ const { typeParameters } = candidate;
18706
+ if (!typeParameters) {
18707
+ return candidate;
18708
+ }
18709
+
18710
+ const typeArgumentNodes: ReadonlyArray<TypeNode> = callLikeExpressionMayHaveTypeArguments(node) ? node.typeArguments || emptyArray : emptyArray;
18711
+ const typeArguments = typeArgumentNodes.map(n => getTypeOfNode(n) || anyType);
18712
+ while (typeArguments.length > typeParameters.length) {
18713
+ typeArguments.pop();
18714
+ }
18715
+ while (typeArguments.length < typeParameters.length) {
18716
+ typeArguments.push(getConstraintFromTypeParameter(typeParameters[typeArguments.length]) || getDefaultTypeArgumentType(isInJavaScriptFile(node)));
18717
+ }
18718
+ const instantiated = createSignatureInstantiation(candidate, typeArguments);
18719
+ candidates[bestIndex] = instantiated;
18720
+ return instantiated;
18721
+ }
18722
+
18664
18723
function getLongestCandidateIndex(candidates: Signature[], argsCount: number): number {
18665
18724
let maxParamsIndex = -1;
18666
18725
let maxParams = -1;
@@ -19400,12 +19459,15 @@ namespace ts {
19400
19459
}
19401
19460
19402
19461
function getTypeAtPosition(signature: Signature, pos: number): Type {
19462
+ return tryGetTypeAtPosition(signature, pos) || anyType;
19463
+ }
19464
+
19465
+ function tryGetTypeAtPosition(signature: Signature, pos: number): Type | undefined {
19403
19466
return signature.hasRestParameter ?
19404
19467
pos < signature.parameters.length - 1 ? getTypeOfParameter(signature.parameters[pos]) : getRestTypeOfSignature(signature) :
19405
- pos < signature.parameters.length ? getTypeOfParameter(signature.parameters[pos]) : anyType ;
19468
+ pos < signature.parameters.length ? getTypeOfParameter(signature.parameters[pos]) : undefined ;
19406
19469
}
19407
19470
19408
-
19409
19471
function getTypeOfFirstParameterOfSignature(signature: Signature) {
19410
19472
return getTypeOfFirstParameterOfSignatureWithFallback(signature, neverType);
19411
19473
}
0 commit comments