Skip to content

Fix union of variadic functions #5384

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 23, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5620,11 +5620,10 @@ namespace ts {
// M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N
source = getErasedSignature(source);
target = getErasedSignature(target);
let sourceLen = source.parameters.length;
let targetLen = target.parameters.length;
for (let i = 0; i < targetLen; i++) {
let s = source.hasRestParameter && i === sourceLen - 1 ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]);
let t = target.hasRestParameter && i === targetLen - 1 ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]);
let s = isRestParameterIndex(source, i) ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]);
let t = isRestParameterIndex(target, i) ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]);
let related = compareTypes(s, t);
if (!related) {
return Ternary.False;
Expand All @@ -5637,6 +5636,10 @@ namespace ts {
return result;
}

function isRestParameterIndex(signature: Signature, parameterIndex: number) {
return signature.hasRestParameter && parameterIndex >= signature.parameters.length - 1;
}

function isSupertypeOfEach(candidate: Type, types: Type[]): boolean {
for (let type of types) {
if (candidate !== type && !isTypeSubtypeOf(type, candidate)) return false;
Expand Down Expand Up @@ -6798,8 +6801,9 @@ namespace ts {
}

// If last parameter is contextually rest parameter get its type
if (indexOfParameter === (func.parameters.length - 1) &&
funcHasRestParameters && contextualSignature.hasRestParameter && func.parameters.length >= contextualSignature.parameters.length) {
if (funcHasRestParameters &&
indexOfParameter === (func.parameters.length - 1) &&
isRestParameterIndex(contextualSignature, func.parameters.length - 1)) {
return getTypeOfSymbol(lastOrUndefined(contextualSignature.parameters));
}
}
Expand Down Expand Up @@ -8390,7 +8394,7 @@ namespace ts {
// If spread arguments are present, check that they correspond to a rest parameter. If so, no
// further checking is necessary.
if (spreadArgIndex >= 0) {
return signature.hasRestParameter && spreadArgIndex >= signature.parameters.length - 1;
return isRestParameterIndex(signature, spreadArgIndex);
}

// Too many arguments implies incorrect arity.
Expand Down Expand Up @@ -9381,7 +9385,7 @@ namespace ts {
let contextualParameterType = getTypeAtPosition(context, i);
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
}
if (signature.hasRestParameter && context.hasRestParameter && signature.parameters.length >= context.parameters.length) {
if (signature.hasRestParameter && isRestParameterIndex(context, signature.parameters.length - 1)) {
let parameter = lastOrUndefined(signature.parameters);
let contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters));
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
Expand Down
8 changes: 7 additions & 1 deletion tests/baselines/reference/unionTypeCallSignatures.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@ tests/cases/conformance/types/union/unionTypeCallSignatures.ts(67,12): error TS2
tests/cases/conformance/types/union/unionTypeCallSignatures.ts(68,12): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/conformance/types/union/unionTypeCallSignatures.ts(69,12): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/conformance/types/union/unionTypeCallSignatures.ts(70,12): error TS2346: Supplied parameters do not match any signature of call target.
tests/cases/conformance/types/union/unionTypeCallSignatures.ts(73,12): error TS2346: Supplied parameters do not match any signature of call target.


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

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

6 changes: 6 additions & 0 deletions tests/baselines/reference/unionTypeCallSignatures.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature
strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature
strOrNum = unionWithRestParameter3(); // error no call signature

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


//// [unionTypeCallSignatures.js]
Expand Down Expand Up @@ -132,3 +135,6 @@ strOrNum = unionWithRestParameter3('hello', 10); // error no call signature
strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature
strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature
strOrNum = unionWithRestParameter3(); // error no call signature
var unionWithRestParameter4;
strOrNum = unionWithRestParameter4("hello"); // error supplied parameters do not match any call signature
strOrNum = unionWithRestParameter4("hello", "world");
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,6 @@ strOrNum = unionWithRestParameter3('hello', 10, 11); // error no call signature
strOrNum = unionWithRestParameter3('hello', "hello"); // error no call signature
strOrNum = unionWithRestParameter3(); // error no call signature

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