diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7371f9a4ac5..fd6b1d81818 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5636,11 +5636,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; @@ -5653,6 +5652,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; @@ -6814,8 +6817,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)); } } @@ -8406,7 +8410,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. @@ -9397,7 +9401,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); diff --git a/tests/baselines/reference/unionTypeCallSignatures.errors.txt b/tests/baselines/reference/unionTypeCallSignatures.errors.txt index ebe38a589ee..bf1de6ff8e8 100644 --- a/tests/baselines/reference/unionTypeCallSignatures.errors.txt +++ b/tests/baselines/reference/unionTypeCallSignatures.errors.txt @@ -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; @@ -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"); \ No newline at end of file diff --git a/tests/baselines/reference/unionTypeCallSignatures.js b/tests/baselines/reference/unionTypeCallSignatures.js index fc3dfc8ebbc..103d92fbef3 100644 --- a/tests/baselines/reference/unionTypeCallSignatures.js +++ b/tests/baselines/reference/unionTypeCallSignatures.js @@ -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] @@ -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"); diff --git a/tests/cases/conformance/types/union/unionTypeCallSignatures.ts b/tests/cases/conformance/types/union/unionTypeCallSignatures.ts index ca599329743..a25d27d9a29 100644 --- a/tests/cases/conformance/types/union/unionTypeCallSignatures.ts +++ b/tests/cases/conformance/types/union/unionTypeCallSignatures.ts @@ -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");