@@ -7702,9 +7702,13 @@ namespace ts {
7702
7702
return !signature.resolvedReturnType && findResolutionCycleStartIndex(signature, TypeSystemPropertyName.ResolvedReturnType) >= 0;
7703
7703
}
7704
7704
7705
- function getRestTypeOfSignature(signature: Signature) {
7705
+ function getRestTypeOfSignature(signature: Signature): Type {
7706
+ return tryGetRestTypeOfSignature(signature) || anyType;
7707
+ }
7708
+
7709
+ function tryGetRestTypeOfSignature(signature: Signature): Type | undefined {
7706
7710
const type = getTypeOfRestParameter(signature);
7707
- return type && getIndexTypeOfType(type, IndexKind.Number) || anyType ;
7711
+ return type && getIndexTypeOfType(type, IndexKind.Number);
7708
7712
}
7709
7713
7710
7714
function getSignatureInstantiation(signature: Signature, typeArguments: Type[] | undefined, isJavascript: boolean): Signature {
@@ -19069,38 +19073,7 @@ namespace ts {
19069
19073
diagnostics.add(createDiagnosticForNode(node, fallbackError));
19070
19074
}
19071
19075
19072
- // No signature was applicable. We have already reported the errors for the invalid signature.
19073
- // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature.
19074
- // Pick the longest signature. This way we can get a contextual type for cases like:
19075
- // declare function f(a: { xa: number; xb: number; }, b: number);
19076
- // f({ |
19077
- // Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like:
19078
- // declare function f<T>(k: keyof T);
19079
- // f<Foo>("
19080
- if (!produceDiagnostics) {
19081
- Debug.assert(candidates.length > 0); // Else would have exited above.
19082
- const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args!.length : apparentArgumentCount);
19083
- const candidate = candidates[bestIndex];
19084
-
19085
- const { typeParameters } = candidate;
19086
- if (typeParameters && callLikeExpressionMayHaveTypeArguments(node) && node.typeArguments) {
19087
- const typeArguments = node.typeArguments.map(getTypeOfNode) as Type[]; // TODO: GH#18217
19088
- while (typeArguments.length > typeParameters.length) {
19089
- typeArguments.pop();
19090
- }
19091
- while (typeArguments.length < typeParameters.length) {
19092
- typeArguments.push(getDefaultTypeArgumentType(isInJavaScriptFile(node)));
19093
- }
19094
-
19095
- const instantiated = createSignatureInstantiation(candidate, typeArguments);
19096
- candidates[bestIndex] = instantiated;
19097
- return instantiated;
19098
- }
19099
-
19100
- return candidate;
19101
- }
19102
-
19103
- return resolveErrorCall(node);
19076
+ return produceDiagnostics || !args ? resolveErrorCall(node) : getCandidateForOverloadFailure(node, candidates, args, !!candidatesOutArray);
19104
19077
19105
19078
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>, signatureHelpTrailingComma = false) {
19106
19079
candidateForArgumentError = undefined;
@@ -19171,6 +19144,97 @@ namespace ts {
19171
19144
}
19172
19145
}
19173
19146
19147
+ // No signature was applicable. We have already reported the errors for the invalid signature.
19148
+ // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature.
19149
+ function getCandidateForOverloadFailure(
19150
+ node: CallLikeExpression,
19151
+ candidates: Signature[],
19152
+ args: ReadonlyArray<Expression>,
19153
+ hasCandidatesOutArray: boolean,
19154
+ ): Signature {
19155
+ Debug.assert(candidates.length > 0); // Else should not have called this.
19156
+ // Normally we will combine overloads. Skip this if they have type parameters since that's hard to combine.
19157
+ // Don't do this if there is a `candidatesOutArray`,
19158
+ // because then we want the chosen best candidate to be one of the overloads, not a combination.
19159
+ return hasCandidatesOutArray || candidates.length === 1 || candidates.some(c => !!c.typeParameters)
19160
+ ? pickLongestCandidateSignature(node, candidates, args)
19161
+ : createUnionOfSignaturesForOverloadFailure(candidates);
19162
+ }
19163
+
19164
+ function createUnionOfSignaturesForOverloadFailure(candidates: ReadonlyArray<Signature>): Signature {
19165
+ const thisParameters = mapDefined(candidates, c => c.thisParameter);
19166
+ let thisParameter: Symbol | undefined;
19167
+ if (thisParameters.length) {
19168
+ thisParameter = createCombinedSymbolFromTypes(thisParameters, thisParameters.map(getTypeOfParameter));
19169
+ }
19170
+ const { min: minArgumentCount, max: maxNonRestParam } = minAndMax(candidates, getNumNonRestParameters);
19171
+ const parameters: Symbol[] = [];
19172
+ for (let i = 0; i < maxNonRestParam; i++) {
19173
+ const symbols = mapDefined(candidates, ({ parameters, hasRestParameter }) => hasRestParameter ?
19174
+ i < parameters.length - 1 ? parameters[i] : last(parameters) :
19175
+ i < parameters.length ? parameters[i] : undefined);
19176
+ Debug.assert(symbols.length !== 0);
19177
+ parameters.push(createCombinedSymbolFromTypes(symbols, mapDefined(candidates, candidate => tryGetTypeAtPosition(candidate, i))));
19178
+ }
19179
+ const restParameterSymbols = mapDefined(candidates, c => c.hasRestParameter ? last(c.parameters) : undefined);
19180
+ const hasRestParameter = restParameterSymbols.length !== 0;
19181
+ if (hasRestParameter) {
19182
+ const type = createArrayType(getUnionType(mapDefined(candidates, tryGetRestTypeOfSignature), UnionReduction.Subtype));
19183
+ parameters.push(createCombinedSymbolForOverloadFailure(restParameterSymbols, type));
19184
+ }
19185
+ return createSignature(
19186
+ candidates[0].declaration,
19187
+ /*typeParameters*/ undefined, // Before calling this we tested for `!candidates.some(c => !!c.typeParameters)`.
19188
+ thisParameter,
19189
+ parameters,
19190
+ /*resolvedReturnType*/ getIntersectionType(candidates.map(getReturnTypeOfSignature)),
19191
+ /*typePredicate*/ undefined,
19192
+ minArgumentCount,
19193
+ hasRestParameter,
19194
+ /*hasLiteralTypes*/ candidates.some(c => c.hasLiteralTypes));
19195
+ }
19196
+
19197
+ function getNumNonRestParameters(signature: Signature): number {
19198
+ const numParams = signature.parameters.length;
19199
+ return signature.hasRestParameter ? numParams - 1 : numParams;
19200
+ }
19201
+
19202
+ function createCombinedSymbolFromTypes(sources: ReadonlyArray<Symbol>, types: Type[]): Symbol {
19203
+ return createCombinedSymbolForOverloadFailure(sources, getUnionType(types, UnionReduction.Subtype));
19204
+ }
19205
+
19206
+ function createCombinedSymbolForOverloadFailure(sources: ReadonlyArray<Symbol>, type: Type): Symbol {
19207
+ // This function is currently only used for erroneous overloads, so it's good enough to just use the first source.
19208
+ return createSymbolWithType(first(sources), type);
19209
+ }
19210
+
19211
+ function pickLongestCandidateSignature(node: CallLikeExpression, candidates: Signature[], args: ReadonlyArray<Expression>): Signature {
19212
+ // Pick the longest signature. This way we can get a contextual type for cases like:
19213
+ // declare function f(a: { xa: number; xb: number; }, b: number);
19214
+ // f({ |
19215
+ // Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like:
19216
+ // declare function f<T>(k: keyof T);
19217
+ // f<Foo>("
19218
+ const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args.length : apparentArgumentCount);
19219
+ const candidate = candidates[bestIndex];
19220
+ const { typeParameters } = candidate;
19221
+ if (!typeParameters) {
19222
+ return candidate;
19223
+ }
19224
+
19225
+ const typeArgumentNodes: ReadonlyArray<TypeNode> = callLikeExpressionMayHaveTypeArguments(node) ? node.typeArguments || emptyArray : emptyArray;
19226
+ const typeArguments = typeArgumentNodes.map(n => getTypeOfNode(n) || anyType);
19227
+ while (typeArguments.length > typeParameters.length) {
19228
+ typeArguments.pop();
19229
+ }
19230
+ while (typeArguments.length < typeParameters.length) {
19231
+ typeArguments.push(getConstraintFromTypeParameter(typeParameters[typeArguments.length]) || getDefaultTypeArgumentType(isInJavaScriptFile(node)));
19232
+ }
19233
+ const instantiated = createSignatureInstantiation(candidate, typeArguments);
19234
+ candidates[bestIndex] = instantiated;
19235
+ return instantiated;
19236
+ }
19237
+
19174
19238
function getLongestCandidateIndex(candidates: Signature[], argsCount: number): number {
19175
19239
let maxParamsIndex = -1;
19176
19240
let maxParams = -1;
@@ -19955,6 +20019,10 @@ namespace ts {
19955
20019
}
19956
20020
19957
20021
function getTypeAtPosition(signature: Signature, pos: number): Type {
20022
+ return tryGetTypeAtPosition(signature, pos) || anyType;
20023
+ }
20024
+
20025
+ function tryGetTypeAtPosition(signature: Signature, pos: number): Type | undefined {
19958
20026
const paramCount = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
19959
20027
if (pos < paramCount) {
19960
20028
return getTypeOfParameter(signature.parameters[pos]);
@@ -19970,9 +20038,9 @@ namespace ts {
19970
20038
return tupleRestType;
19971
20039
}
19972
20040
}
19973
- return getIndexTypeOfType(restType, IndexKind.Number) || anyType ;
20041
+ return getIndexTypeOfType(restType, IndexKind.Number);
19974
20042
}
19975
- return anyType ;
20043
+ return undefined ;
19976
20044
}
19977
20045
19978
20046
function getRestTypeAtPosition(source: Signature, pos: number): Type {
0 commit comments