@@ -7595,13 +7595,17 @@ namespace ts {
7595
7595
}
7596
7596
7597
7597
function getRestTypeOfSignature(signature: Signature): Type {
7598
+ return tryGetRestTypeOfSignature(signature) || anyType;
7599
+ }
7600
+
7601
+ function tryGetRestTypeOfSignature(signature: Signature): Type | undefined {
7598
7602
if (signature.hasRestParameter) {
7599
7603
const type = getTypeOfSymbol(last(signature.parameters));
7600
7604
if (getObjectFlags(type) & ObjectFlags.Reference && (<TypeReference>type).target === globalArrayType) {
7601
7605
return (<TypeReference>type).typeArguments![0];
7602
7606
}
7603
7607
}
7604
- return anyType ;
7608
+ return undefined ;
7605
7609
}
7606
7610
7607
7611
function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean): Signature {
@@ -18548,38 +18552,7 @@ namespace ts {
18548
18552
diagnostics.add(createDiagnosticForNode(node, fallbackError));
18549
18553
}
18550
18554
18551
- // No signature was applicable. We have already reported the errors for the invalid signature.
18552
- // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature.
18553
- // Pick the longest signature. This way we can get a contextual type for cases like:
18554
- // declare function f(a: { xa: number; xb: number; }, b: number);
18555
- // f({ |
18556
- // Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like:
18557
- // declare function f<T>(k: keyof T);
18558
- // f<Foo>("
18559
- if (!produceDiagnostics) {
18560
- Debug.assert(candidates.length > 0); // Else would have exited above.
18561
- const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args!.length : apparentArgumentCount);
18562
- const candidate = candidates[bestIndex];
18563
-
18564
- const { typeParameters } = candidate;
18565
- if (typeParameters && callLikeExpressionMayHaveTypeArguments(node) && node.typeArguments) {
18566
- const typeArguments = node.typeArguments.map(getTypeOfNode) as Type[]; // TODO: GH#18217
18567
- while (typeArguments.length > typeParameters.length) {
18568
- typeArguments.pop();
18569
- }
18570
- while (typeArguments.length < typeParameters.length) {
18571
- typeArguments.push(getDefaultTypeArgumentType(isInJavaScriptFile(node)));
18572
- }
18573
-
18574
- const instantiated = createSignatureInstantiation(candidate, typeArguments);
18575
- candidates[bestIndex] = instantiated;
18576
- return instantiated;
18577
- }
18578
-
18579
- return candidate;
18580
- }
18581
-
18582
- return resolveErrorCall(node);
18555
+ return produceDiagnostics || !args ? resolveErrorCall(node) : getCandidateForOverloadFailure(node, candidates, args, !!candidatesOutArray);
18583
18556
18584
18557
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>, signatureHelpTrailingComma = false) {
18585
18558
candidateForArgumentError = undefined;
@@ -18650,6 +18623,92 @@ namespace ts {
18650
18623
}
18651
18624
}
18652
18625
18626
+ // No signature was applicable. We have already reported the errors for the invalid signature.
18627
+ // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature.
18628
+ function getCandidateForOverloadFailure(
18629
+ node: CallLikeExpression,
18630
+ candidates: Signature[],
18631
+ args: ReadonlyArray<Expression>,
18632
+ hasCandidatesOutArray: boolean,
18633
+ ): Signature {
18634
+ Debug.assert(candidates.length > 0); // Else should not have called this.
18635
+ // Normally we will combine overloads. Skip this if they have type parameters since that's hard to combine.
18636
+ // Don't do this if there is a `candidatesOutArray`,
18637
+ // because then we want the chosen best candidate to be one of the overloads, not a combination.
18638
+ return hasCandidatesOutArray || candidates.length === 1 || candidates.some(c => !!c.typeParameters)
18639
+ ? pickLongestCandidateSignature(node, candidates, args)
18640
+ : createUnionOfSignaturesForOverloadFailure(candidates);
18641
+ }
18642
+
18643
+ function createUnionOfSignaturesForOverloadFailure(candidates: ReadonlyArray<Signature>): Signature {
18644
+ const thisParameters = mapDefined(candidates, c => c.thisParameter);
18645
+ let thisParameter: Symbol | undefined;
18646
+ if (thisParameters.length) {
18647
+ thisParameter = createCombinedSymbolFromTypes(thisParameters, thisParameters.map(getTypeOfParameter));
18648
+ }
18649
+ const { min: minArgumentCount, max: maxNonRestParam } = minAndMax(candidates, getNumNonRestParameters);
18650
+ const parameters: Symbol[] = [];
18651
+ for (let i = 0; i < maxNonRestParam; i++) {
18652
+ const symbols = mapDefined(candidates, ({ parameters, hasRestParameter }) => hasRestParameter ?
18653
+ i < parameters.length - 1 ? parameters[i] : last(parameters) :
18654
+ i < parameters.length ? parameters[i] : undefined);
18655
+ Debug.assert(symbols.length !== 0);
18656
+ parameters.push(createCombinedSymbolFromTypes(symbols, mapDefined(candidates, candidate => tryGetTypeAtPosition(candidate, i))));
18657
+ }
18658
+ const restParameterSymbols = mapDefined(candidates, c => c.hasRestParameter ? last(c.parameters) : undefined);
18659
+ const hasRestParameter = restParameterSymbols.length !== 0;
18660
+ if (hasRestParameter) {
18661
+ const type = createArrayType(getUnionType(mapDefined(candidates, tryGetRestTypeOfSignature), UnionReduction.Subtype));
18662
+ parameters.push(createCombinedSymbolForOverloadFailure(restParameterSymbols, type));
18663
+ }
18664
+ return createSignature(
18665
+ candidates[0].declaration,
18666
+ /*typeParameters*/ undefined, // Before calling this we tested for `!candidates.some(c => !!c.typeParameters)`.
18667
+ thisParameter,
18668
+ parameters,
18669
+ /*resolvedReturnType*/ getIntersectionType(candidates.map(getReturnTypeOfSignature)),
18670
+ /*typePredicate*/ undefined,
18671
+ minArgumentCount,
18672
+ hasRestParameter,
18673
+ /*hasLiteralTypes*/ candidates.some(c => c.hasLiteralTypes));
18674
+ }
18675
+
18676
+ function createCombinedSymbolFromTypes(sources: ReadonlyArray<Symbol>, types: Type[]): Symbol {
18677
+ return createCombinedSymbolForOverloadFailure(sources, getUnionType(types, UnionReduction.Subtype));
18678
+ }
18679
+
18680
+ function createCombinedSymbolForOverloadFailure(sources: ReadonlyArray<Symbol>, type: Type): Symbol {
18681
+ // This function is currently only used for erroneous overloads, so it's good enough to just use the first source.
18682
+ return createSymbolWithType(first(sources), type);
18683
+ }
18684
+
18685
+ function pickLongestCandidateSignature(node: CallLikeExpression, candidates: Signature[], args: ReadonlyArray<Expression>): Signature {
18686
+ // Pick the longest signature. This way we can get a contextual type for cases like:
18687
+ // declare function f(a: { xa: number; xb: number; }, b: number);
18688
+ // f({ |
18689
+ // Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like:
18690
+ // declare function f<T>(k: keyof T);
18691
+ // f<Foo>("
18692
+ const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args.length : apparentArgumentCount);
18693
+ const candidate = candidates[bestIndex];
18694
+ const { typeParameters } = candidate;
18695
+ if (!typeParameters) {
18696
+ return candidate;
18697
+ }
18698
+
18699
+ const typeArgumentNodes: ReadonlyArray<TypeNode> = callLikeExpressionMayHaveTypeArguments(node) ? node.typeArguments || emptyArray : emptyArray;
18700
+ const typeArguments = typeArgumentNodes.map(n => getTypeOfNode(n) || anyType);
18701
+ while (typeArguments.length > typeParameters.length) {
18702
+ typeArguments.pop();
18703
+ }
18704
+ while (typeArguments.length < typeParameters.length) {
18705
+ typeArguments.push(getConstraintFromTypeParameter(typeParameters[typeArguments.length]) || getDefaultTypeArgumentType(isInJavaScriptFile(node)));
18706
+ }
18707
+ const instantiated = createSignatureInstantiation(candidate, typeArguments);
18708
+ candidates[bestIndex] = instantiated;
18709
+ return instantiated;
18710
+ }
18711
+
18653
18712
function getLongestCandidateIndex(candidates: Signature[], argsCount: number): number {
18654
18713
let maxParamsIndex = -1;
18655
18714
let maxParams = -1;
@@ -19389,12 +19448,15 @@ namespace ts {
19389
19448
}
19390
19449
19391
19450
function getTypeAtPosition(signature: Signature, pos: number): Type {
19451
+ return tryGetTypeAtPosition(signature, pos) || anyType;
19452
+ }
19453
+
19454
+ function tryGetTypeAtPosition(signature: Signature, pos: number): Type | undefined {
19392
19455
return signature.hasRestParameter ?
19393
19456
pos < signature.parameters.length - 1 ? getTypeOfParameter(signature.parameters[pos]) : getRestTypeOfSignature(signature) :
19394
- pos < signature.parameters.length ? getTypeOfParameter(signature.parameters[pos]) : anyType ;
19457
+ pos < signature.parameters.length ? getTypeOfParameter(signature.parameters[pos]) : undefined ;
19395
19458
}
19396
19459
19397
-
19398
19460
function getTypeOfFirstParameterOfSignature(signature: Signature) {
19399
19461
return getTypeOfFirstParameterOfSignatureWithFallback(signature, neverType);
19400
19462
}
0 commit comments