Skip to content

Commit c4e5468

Browse files
committed
Merge pull request microsoft#5384 from Microsoft/fix-union-of-variadic-functions
Fix union of variadic functions
2 parents d26a4c8 + ab2994f commit c4e5468

File tree

4 files changed

+27
-8
lines changed

4 files changed

+27
-8
lines changed

src/compiler/checker.ts

+11-7
Original file line numberDiff line numberDiff line change
@@ -5636,11 +5636,10 @@ namespace ts {
56365636
// M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N
56375637
source = getErasedSignature(source);
56385638
target = getErasedSignature(target);
5639-
let sourceLen = source.parameters.length;
56405639
let targetLen = target.parameters.length;
56415640
for (let i = 0; i < targetLen; i++) {
5642-
let s = source.hasRestParameter && i === sourceLen - 1 ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]);
5643-
let t = target.hasRestParameter && i === targetLen - 1 ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]);
5641+
let s = isRestParameterIndex(source, i) ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]);
5642+
let t = isRestParameterIndex(target, i) ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]);
56445643
let related = compareTypes(s, t);
56455644
if (!related) {
56465645
return Ternary.False;
@@ -5653,6 +5652,10 @@ namespace ts {
56535652
return result;
56545653
}
56555654

5655+
function isRestParameterIndex(signature: Signature, parameterIndex: number) {
5656+
return signature.hasRestParameter && parameterIndex >= signature.parameters.length - 1;
5657+
}
5658+
56565659
function isSupertypeOfEach(candidate: Type, types: Type[]): boolean {
56575660
for (let type of types) {
56585661
if (candidate !== type && !isTypeSubtypeOf(type, candidate)) return false;
@@ -6814,8 +6817,9 @@ namespace ts {
68146817
}
68156818

68166819
// If last parameter is contextually rest parameter get its type
6817-
if (indexOfParameter === (func.parameters.length - 1) &&
6818-
funcHasRestParameters && contextualSignature.hasRestParameter && func.parameters.length >= contextualSignature.parameters.length) {
6820+
if (funcHasRestParameters &&
6821+
indexOfParameter === (func.parameters.length - 1) &&
6822+
isRestParameterIndex(contextualSignature, func.parameters.length - 1)) {
68196823
return getTypeOfSymbol(lastOrUndefined(contextualSignature.parameters));
68206824
}
68216825
}
@@ -8406,7 +8410,7 @@ namespace ts {
84068410
// If spread arguments are present, check that they correspond to a rest parameter. If so, no
84078411
// further checking is necessary.
84088412
if (spreadArgIndex >= 0) {
8409-
return signature.hasRestParameter && spreadArgIndex >= signature.parameters.length - 1;
8413+
return isRestParameterIndex(signature, spreadArgIndex);
84108414
}
84118415

84128416
// Too many arguments implies incorrect arity.
@@ -9397,7 +9401,7 @@ namespace ts {
93979401
let contextualParameterType = getTypeAtPosition(context, i);
93989402
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
93999403
}
9400-
if (signature.hasRestParameter && context.hasRestParameter && signature.parameters.length >= context.parameters.length) {
9404+
if (signature.hasRestParameter && isRestParameterIndex(context, signature.parameters.length - 1)) {
94019405
let parameter = lastOrUndefined(signature.parameters);
94029406
let contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters));
94039407
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);

tests/baselines/reference/unionTypeCallSignatures.errors.txt

+7-1
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(67,12): error TS2
2828
tests/cases/conformance/types/union/unionTypeCallSignatures.ts(68,12): error TS2346: Supplied parameters do not match any signature of call target.
2929
tests/cases/conformance/types/union/unionTypeCallSignatures.ts(69,12): error TS2346: Supplied parameters do not match any signature of call target.
3030
tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2346: Supplied parameters do not match any signature of call target.
31+
tests/cases/conformance/types/union/unionTypeCallSignatures.ts(73,12): error TS2346: Supplied parameters do not match any signature of call target.
3132

3233

33-
==== tests/cases/conformance/types/union/unionTypeCallSignatures.ts (30 errors) ====
34+
==== tests/cases/conformance/types/union/unionTypeCallSignatures.ts (31 errors) ====
3435
var numOrDate: number | Date;
3536
var strOrBoolean: string | boolean;
3637
var strOrNum: string | number;
@@ -162,4 +163,9 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2
162163
~~~~~~~~~~~~~~~~~~~~~~~~~
163164
!!! error TS2346: Supplied parameters do not match any signature of call target.
164165

166+
var unionWithRestParameter4: { (...a: string[]): string; } | { (a: string, b: string): number; };
167+
strOrNum = unionWithRestParameter4("hello"); // error supplied parameters do not match any call signature
168+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
169+
!!! error TS2346: Supplied parameters do not match any signature of call target.
170+
strOrNum = unionWithRestParameter4("hello", "world");
165171

tests/baselines/reference/unionTypeCallSignatures.js

+6
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature
7070
strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature
7171
strOrNum = unionWithRestParameter3(); // error no call signature
7272

73+
var unionWithRestParameter4: { (...a: string[]): string; } | { (a: string, b: string): number; };
74+
strOrNum = unionWithRestParameter4("hello"); // error supplied parameters do not match any call signature
75+
strOrNum = unionWithRestParameter4("hello", "world");
7376

7477

7578
//// [unionTypeCallSignatures.js]
@@ -132,3 +135,6 @@ strOrNum = unionWithRestParameter3('hello', 10); // error no call signature
132135
strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature
133136
strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature
134137
strOrNum = unionWithRestParameter3(); // error no call signature
138+
var unionWithRestParameter4;
139+
strOrNum = unionWithRestParameter4("hello"); // error supplied parameters do not match any call signature
140+
strOrNum = unionWithRestParameter4("hello", "world");

tests/cases/conformance/types/union/unionTypeCallSignatures.ts

+3
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,6 @@ strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature
6969
strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature
7070
strOrNum = unionWithRestParameter3(); // error no call signature
7171

72+
var unionWithRestParameter4: { (...a: string[]): string; } | { (a: string, b: string): number; };
73+
strOrNum = unionWithRestParameter4("hello"); // error supplied parameters do not match any call signature
74+
strOrNum = unionWithRestParameter4("hello", "world");

0 commit comments

Comments
 (0)