@@ -6682,13 +6682,17 @@ namespace ts {
6682
6682
}
6683
6683
6684
6684
function getRestTypeOfSignature(signature: Signature): Type {
6685
+ return tryGetRestTypeOfSignature(signature) || anyType;
6686
+ }
6687
+
6688
+ function tryGetRestTypeOfSignature(signature: Signature): Type | undefined {
6685
6689
if (signature.hasRestParameter) {
6686
6690
const type = getTypeOfSymbol(lastOrUndefined(signature.parameters));
6687
6691
if (getObjectFlags(type) & ObjectFlags.Reference && (<TypeReference>type).target === globalArrayType) {
6688
6692
return (<TypeReference>type).typeArguments[0];
6689
6693
}
6690
6694
}
6691
- return anyType ;
6695
+ return undefined ;
6692
6696
}
6693
6697
6694
6698
function getSignatureInstantiation(signature: Signature, typeArguments: Type[], isJavascript: boolean): Signature {
@@ -10430,6 +10434,11 @@ namespace ts {
10430
10434
return symbol;
10431
10435
}
10432
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
+
10433
10442
function transformTypeOfMembers(type: Type, f: (propertyType: Type) => Type) {
10434
10443
const members = createSymbolTable();
10435
10444
for (const property of getPropertiesOfObjectType(type)) {
@@ -16433,35 +16442,8 @@ namespace ts {
16433
16442
diagnostics.add(createDiagnosticForNode(node, fallbackError));
16434
16443
}
16435
16444
16436
- // No signature was applicable. We have already reported the errors for the invalid signature.
16437
- // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature.
16438
- // Pick the longest signature. This way we can get a contextual type for cases like:
16439
- // declare function f(a: { xa: number; xb: number; }, b: number);
16440
- // f({ |
16441
- // Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like:
16442
- // declare function f<T>(k: keyof T);
16443
- // f<Foo>("
16444
16445
if (!produceDiagnostics) {
16445
- Debug.assert(candidates.length > 0); // Else would have exited above.
16446
- const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args.length : apparentArgumentCount);
16447
- const candidate = candidates[bestIndex];
16448
-
16449
- const { typeParameters } = candidate;
16450
- if (typeParameters && callLikeExpressionMayHaveTypeArguments(node) && node.typeArguments) {
16451
- const typeArguments = node.typeArguments.map(getTypeOfNode);
16452
- while (typeArguments.length > typeParameters.length) {
16453
- typeArguments.pop();
16454
- }
16455
- while (typeArguments.length < typeParameters.length) {
16456
- typeArguments.push(getDefaultTypeArgumentType(isInJavaScriptFile(node)));
16457
- }
16458
-
16459
- const instantiated = createSignatureInstantiation(candidate, typeArguments);
16460
- candidates[bestIndex] = instantiated;
16461
- return instantiated;
16462
- }
16463
-
16464
- return candidate;
16446
+ return getCandidateForOverloadFailure(node, candidates, args);
16465
16447
}
16466
16448
16467
16449
return resolveErrorCall(node);
@@ -16535,6 +16517,82 @@ namespace ts {
16535
16517
}
16536
16518
}
16537
16519
16520
+ // No signature was applicable. We have already reported the errors for the invalid signature.
16521
+ // If this is a type resolution session, e.g. Language Service, try to get better information than anySignature.
16522
+ function getCandidateForOverloadFailure(node: CallLikeExpression, candidates: Signature[], args: ReadonlyArray<Expression>): Signature {
16523
+ Debug.assert(candidates.length > 0); // Else should not have called this.
16524
+
16525
+ // Normally we will combine overloads. Skip this if they have type parameters since that's hard to combine.
16526
+ if (candidates.length > 1 && !candidates.some(c => !!c.typeParameters)) {
16527
+ return createUnionOfSignaturesForOverloadFailure(candidates);
16528
+ }
16529
+
16530
+ // Pick the longest signature. This way we can get a contextual type for cases like:
16531
+ // declare function f(a: { xa: number; xb: number; }, b: number);
16532
+ // f({ |
16533
+ // Also, use explicitly-supplied type arguments if they are provided, so we can get a contextual signature in cases like:
16534
+ // declare function f<T>(k: keyof T);
16535
+ // f<Foo>("
16536
+ const bestIndex = getLongestCandidateIndex(candidates, apparentArgumentCount === undefined ? args.length : apparentArgumentCount);
16537
+ const candidate = candidates[bestIndex];
16538
+
16539
+ const { typeParameters } = candidate;
16540
+ if (typeParameters && callLikeExpressionMayHaveTypeArguments(node) && node.typeArguments) {
16541
+ const typeArguments = node.typeArguments.map(getTypeOfNode);
16542
+ while (typeArguments.length > typeParameters.length) {
16543
+ typeArguments.pop();
16544
+ }
16545
+ while (typeArguments.length < typeParameters.length) {
16546
+ typeArguments.push(getDefaultTypeArgumentType(isInJavaScriptFile(node)));
16547
+ }
16548
+
16549
+ const instantiated = createSignatureInstantiation(candidate, typeArguments);
16550
+ candidates[bestIndex] = instantiated;
16551
+ return instantiated;
16552
+ }
16553
+
16554
+ return candidate;
16555
+ }
16556
+
16557
+ function createUnionOfSignaturesForOverloadFailure(candidates: ReadonlyArray<Signature>): Signature {
16558
+ const thisParameters = mapDefined(candidates, c => c.thisParameter);
16559
+ let thisParameter: Symbol | undefined;
16560
+ if (thisParameters.length) {
16561
+ thisParameter = createCombinedSymbolWithType(thisParameters, getUnionType(thisParameters.map(getTypeOfParameter), /*subtypeReduction*/ true));
16562
+ }
16563
+
16564
+ const { min: minArgumentCount, max: maxNonRestParam } = minAndMax(candidates, getNumNonRestParameters);
16565
+ const hasRestParameter = candidates.some(c => c.hasRestParameter);
16566
+ const hasLiteralTypes = candidates.some(c => c.hasLiteralTypes);
16567
+ const parameters: ts.Symbol[] = [];
16568
+ for (let i = 0; i < maxNonRestParam; i++) {
16569
+ const symbols = mapDefined(candidates, ({ parameters, hasRestParameter }) => hasRestParameter ?
16570
+ i < parameters.length - 1 ? parameters[i] : last(parameters) :
16571
+ i < parameters.length ? parameters[i] : undefined);
16572
+ Debug.assert(symbols.length !== 0);
16573
+ const types = mapDefined(candidates, candidate => tryGetTypeAtPosition(candidate, i));
16574
+ parameters.push(createCombinedSymbolWithType(symbols, getUnionType(types, /*subtypeReduction*/ true)));
16575
+ }
16576
+
16577
+ if (hasRestParameter) {
16578
+ const symbols = mapDefined(candidates, c => c.hasRestParameter ? last(c.parameters) : undefined);
16579
+ Debug.assert(symbols.length !== 0);
16580
+ const type = createArrayType(getUnionType(mapDefined(candidates, tryGetRestTypeOfSignature), /*subtypeReduction*/ true));
16581
+ parameters.push(createCombinedSymbolWithType(symbols, type));
16582
+ }
16583
+
16584
+ return createSignature(
16585
+ candidates[0].declaration,
16586
+ /*typeParameters*/ undefined,
16587
+ thisParameter,
16588
+ parameters,
16589
+ /*resolvedReturnType*/ unknownType,
16590
+ /*typePredicate*/ undefined,
16591
+ minArgumentCount,
16592
+ hasRestParameter,
16593
+ hasLiteralTypes);
16594
+ }
16595
+
16538
16596
function getLongestCandidateIndex(candidates: Signature[], argsCount: number): number {
16539
16597
let maxParamsIndex = -1;
16540
16598
let maxParams = -1;
@@ -17175,9 +17233,13 @@ namespace ts {
17175
17233
}
17176
17234
17177
17235
function getTypeAtPosition(signature: Signature, pos: number): Type {
17236
+ return tryGetTypeAtPosition(signature, pos) || anyType;
17237
+ }
17238
+
17239
+ function tryGetTypeAtPosition(signature: Signature, pos: number): Type | undefined {
17178
17240
return signature.hasRestParameter ?
17179
17241
pos < signature.parameters.length - 1 ? getTypeOfParameter(signature.parameters[pos]) : getRestTypeOfSignature(signature) :
17180
- pos < signature.parameters.length ? getTypeOfParameter(signature.parameters[pos]) : anyType ;
17242
+ pos < signature.parameters.length ? getTypeOfParameter(signature.parameters[pos]) : undefined ;
17181
17243
}
17182
17244
17183
17245
function getTypeOfFirstParameterOfSignature(signature: Signature) {
0 commit comments