diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4ed83e41eb510..45b48bbcd880f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -25051,22 +25051,40 @@ namespace ts { effectiveParameterCount = args.length === 0 ? effectiveParameterCount : 1; // class may have argumentless ctor functions - still resolve ctor and compare vs props member type effectiveMinimumArguments = Math.min(effectiveMinimumArguments, 1); // sfc may specify context argument - handled by framework and not typechecked } + else if (!node.arguments) { + // This only happens when we have something of the form: 'new C' + Debug.assert(node.kind === SyntaxKind.NewExpression); + return getMinArgumentCount(signature) === 0; + } else { - if (!node.arguments) { - // This only happens when we have something of the form: 'new C' - Debug.assert(node.kind === SyntaxKind.NewExpression); - return getMinArgumentCount(signature) === 0; - } - argCount = signatureHelpTrailingComma ? args.length + 1 : args.length; // If we are missing the close parenthesis, the call is incomplete. callIsIncomplete = node.arguments.end === node.end; - // If a spread argument is present, check that it corresponds to a rest parameter or at least that it's in the valid range. - const spreadArgIndex = getSpreadArgumentIndex(args); - if (spreadArgIndex >= 0) { - return spreadArgIndex >= getMinArgumentCount(signature) && (hasEffectiveRestParameter(signature) || spreadArgIndex < getParameterCount(signature)); + // If one or more spread arguments are present, check that they correspond to a rest parameter or at least that they are in the valid range. + const firstSpreadArgIndex = getSpreadArgumentIndex(args); + if (firstSpreadArgIndex >= 0) { + if (firstSpreadArgIndex === args.length - 1) { + // Special case, handles the munged arguments that we receive in case of a spread in the end (breaks the arg.expression below) + // (see below for code that starts with "const spreadArgument") + return firstSpreadArgIndex >= getMinArgumentCount(signature) && (hasEffectiveRestParameter(signature) || firstSpreadArgIndex < getParameterCount(signature)); + } + + let totalCount = firstSpreadArgIndex; // count previous arguments + for (let i = firstSpreadArgIndex; i < args.length; i++) { + const arg = args[i]; + if (!isSpreadArgument(arg)) { + totalCount += 1; + } + else { + const argType = flowLoopCount ? checkExpression((arg).expression) : checkExpressionCached((arg).expression); + totalCount += isTupleType(argType) ? getTypeArguments(argType).length + : isArrayType(argType) ? 0 + : 1; + } + } + return totalCount >= getMinArgumentCount(signature) && (hasEffectiveRestParameter(signature) || totalCount <= getParameterCount(signature)); } } @@ -25544,7 +25562,7 @@ namespace ts { const spreadArgument = args[length - 1]; const type = flowLoopCount ? checkExpression(spreadArgument.expression) : checkExpressionCached(spreadArgument.expression); if (isTupleType(type)) { - const typeArguments = getTypeArguments(type); + const typeArguments = getTypeArguments(type); const restIndex = type.target.hasRestElement ? typeArguments.length - 1 : -1; const syntheticArgs = map(typeArguments, (t, i) => createSyntheticExpression(spreadArgument, t, /*isSpread*/ i === restIndex, type.target.labeledElementDeclarations?.[i])); return concatenate(args.slice(0, length - 1), syntheticArgs); diff --git a/tests/baselines/reference/callWithSpread3.errors.txt b/tests/baselines/reference/callWithSpread3.errors.txt index 6e45b5ea7979f..71fc0334633f8 100644 --- a/tests/baselines/reference/callWithSpread3.errors.txt +++ b/tests/baselines/reference/callWithSpread3.errors.txt @@ -1,32 +1,75 @@ -tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(5,14): error TS2554: Expected 2 arguments, but got 3. -tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(6,19): error TS2554: Expected 2 arguments, but got 5. -tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(7,19): error TS2556: Expected 2 arguments, but got 4 or more. -tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(8,19): error TS2556: Expected 2 arguments, but got 5 or more. -tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(9,16): error TS2556: Expected 2 arguments, but got 1 or more. -tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(10,9): error TS2554: Expected 2 arguments, but got 3. +tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(14,10): error TS2554: Expected 2 arguments, but got 3. +tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(15,15): error TS2554: Expected 2 arguments, but got 5. +tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(16,15): error TS2556: Expected 2 arguments, but got 4 or more. +tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(17,15): error TS2556: Expected 2 arguments, but got 5 or more. +tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(18,12): error TS2556: Expected 2 arguments, but got 1 or more. +tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(19,5): error TS2554: Expected 2 arguments, but got 3. +tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(20,6): error TS2557: Expected at least 2 arguments, but got 0 or more. +tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(21,6): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. +tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(22,13): error TS2557: Expected at least 2 arguments, but got 1 or more. +tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(23,13): error TS2557: Expected at least 2 arguments, but got 2 or more. +tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(25,7): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. -==== tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts (6 errors) ==== - declare function takeTwo(a: string, b: string): void; - declare const t2: [string, string]; - declare const t3: [string, string, string]; +==== tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts (11 errors) ==== + declare const s2: [string, string]; + declare const s3: [string, string, string]; + declare const s2_: [string, string, ...string[]]; + declare const s_: string[]; + declare const n_: number[]; + declare const s2n_: [string, string, ...number[]]; - takeTwo('a', ...t2); // error on ...t2 - ~~~~~ + declare function fs2(a: string, b: string): void; + declare function fs2_(a: string, b: string, ...c: string[]): void; + declare function fs2n_(a: string, b: string, ...c: number[]): void; + declare function fs5(a: string, b: string, c: string, d: string, e: string): void; + + // error + fs2('a', ...s2); // error on ...s2 + ~~~~~ !!! error TS2554: Expected 2 arguments, but got 3. - takeTwo('a', 'b', 'c', ...t2); // error on 'c' and ...t2 - ~~~~~~~~~~ + fs2('a', 'b', 'c', ...s2); // error on 'c' and ...s2 + ~~~~~~~~~~ !!! error TS2554: Expected 2 arguments, but got 5. - takeTwo('a', 'b', ...t2, 'c'); // error on ...t2 and 'c' - ~~~~~~~~~~ + fs2('a', 'b', ...s2, 'c'); // error on ...s2 and 'c' + ~~~~~~~~~~ !!! error TS2556: Expected 2 arguments, but got 4 or more. - takeTwo('a', 'b', 'c', ...t2, 'd'); // error on 'c', ...t2 and 'd' - ~~~~~~~~~~~~~~~ + fs2('a', 'b', 'c', ...s2, 'd'); // error on 'c', ...s2 and 'd' + ~~~~~~~~~~~~~~~ !!! error TS2556: Expected 2 arguments, but got 5 or more. - takeTwo(...t2, 'a'); // error on 'a' - ~~~ + fs2(...s2, 'a'); // error on 'a' + ~~~ !!! error TS2556: Expected 2 arguments, but got 1 or more. -!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts:1:37: An argument for 'b' was not provided. - takeTwo(...t3); // error on ...t3 - ~~~~~ -!!! error TS2554: Expected 2 arguments, but got 3. \ No newline at end of file +!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts:8:33: An argument for 'b' was not provided. + fs2(...s3); // error on ...s3 + ~~~~~ +!!! error TS2554: Expected 2 arguments, but got 3. + fs2_(...s_); // error on ...s_ + ~~~~~ +!!! error TS2557: Expected at least 2 arguments, but got 0 or more. +!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts:9:23: An argument for 'a' was not provided. + fs2_(...s2n_); // error on ...s2n_ + ~~~~~~~ +!!! error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. + fs2_(...s_, ...s_); // error FIXME: bad error message + ~~~~~ +!!! error TS2557: Expected at least 2 arguments, but got 1 or more. +!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts:9:34: An argument for 'b' was not provided. + fs2_(...s_, ...s_, ...s_); // error FIXME: worse error message + ~~~~~~~~~~~~ +!!! error TS2557: Expected at least 2 arguments, but got 2 or more. + // fs2n_(...s2, ...s_); // FIXME: should be a type error + fs2n_(...s2_); // error on ...s2_ + ~~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. + + // ok + fs2_(...s2_); + fs2_(...s2_, ...s_); + fs2_(...s2_, ...s2_); + fs2_(...s_, ...s2_); + fs2n_(...s2n_); + fs2n_(...s2); + // fs2n_(...s2, ...n_); // FIXME: should compile + fs5(...s2, "foo", ...s2); + \ No newline at end of file diff --git a/tests/baselines/reference/callWithSpread3.js b/tests/baselines/reference/callWithSpread3.js index bcb30625f46ce..6100d0c2112ec 100644 --- a/tests/baselines/reference/callWithSpread3.js +++ b/tests/baselines/reference/callWithSpread3.js @@ -1,14 +1,40 @@ //// [callWithSpread3.ts] -declare function takeTwo(a: string, b: string): void; -declare const t2: [string, string]; -declare const t3: [string, string, string]; +declare const s2: [string, string]; +declare const s3: [string, string, string]; +declare const s2_: [string, string, ...string[]]; +declare const s_: string[]; +declare const n_: number[]; +declare const s2n_: [string, string, ...number[]]; -takeTwo('a', ...t2); // error on ...t2 -takeTwo('a', 'b', 'c', ...t2); // error on 'c' and ...t2 -takeTwo('a', 'b', ...t2, 'c'); // error on ...t2 and 'c' -takeTwo('a', 'b', 'c', ...t2, 'd'); // error on 'c', ...t2 and 'd' -takeTwo(...t2, 'a'); // error on 'a' -takeTwo(...t3); // error on ...t3 +declare function fs2(a: string, b: string): void; +declare function fs2_(a: string, b: string, ...c: string[]): void; +declare function fs2n_(a: string, b: string, ...c: number[]): void; +declare function fs5(a: string, b: string, c: string, d: string, e: string): void; + +// error +fs2('a', ...s2); // error on ...s2 +fs2('a', 'b', 'c', ...s2); // error on 'c' and ...s2 +fs2('a', 'b', ...s2, 'c'); // error on ...s2 and 'c' +fs2('a', 'b', 'c', ...s2, 'd'); // error on 'c', ...s2 and 'd' +fs2(...s2, 'a'); // error on 'a' +fs2(...s3); // error on ...s3 +fs2_(...s_); // error on ...s_ +fs2_(...s2n_); // error on ...s2n_ +fs2_(...s_, ...s_); // error FIXME: bad error message +fs2_(...s_, ...s_, ...s_); // error FIXME: worse error message +// fs2n_(...s2, ...s_); // FIXME: should be a type error +fs2n_(...s2_); // error on ...s2_ + +// ok +fs2_(...s2_); +fs2_(...s2_, ...s_); +fs2_(...s2_, ...s2_); +fs2_(...s_, ...s2_); +fs2n_(...s2n_); +fs2n_(...s2); +// fs2n_(...s2, ...n_); // FIXME: should compile +fs5(...s2, "foo", ...s2); + //// [callWithSpread3.js] var __spreadArrays = (this && this.__spreadArrays) || function () { @@ -18,9 +44,25 @@ var __spreadArrays = (this && this.__spreadArrays) || function () { r[k] = a[j]; return r; }; -takeTwo.apply(void 0, __spreadArrays(['a'], t2)); // error on ...t2 -takeTwo.apply(void 0, __spreadArrays(['a', 'b', 'c'], t2)); // error on 'c' and ...t2 -takeTwo.apply(void 0, __spreadArrays(['a', 'b'], t2, ['c'])); // error on ...t2 and 'c' -takeTwo.apply(void 0, __spreadArrays(['a', 'b', 'c'], t2, ['d'])); // error on 'c', ...t2 and 'd' -takeTwo.apply(void 0, __spreadArrays(t2, ['a'])); // error on 'a' -takeTwo.apply(void 0, t3); // error on ...t3 +// error +fs2.apply(void 0, __spreadArrays(['a'], s2)); // error on ...s2 +fs2.apply(void 0, __spreadArrays(['a', 'b', 'c'], s2)); // error on 'c' and ...s2 +fs2.apply(void 0, __spreadArrays(['a', 'b'], s2, ['c'])); // error on ...s2 and 'c' +fs2.apply(void 0, __spreadArrays(['a', 'b', 'c'], s2, ['d'])); // error on 'c', ...s2 and 'd' +fs2.apply(void 0, __spreadArrays(s2, ['a'])); // error on 'a' +fs2.apply(void 0, s3); // error on ...s3 +fs2_.apply(void 0, s_); // error on ...s_ +fs2_.apply(void 0, s2n_); // error on ...s2n_ +fs2_.apply(void 0, __spreadArrays(s_, s_)); // error FIXME: bad error message +fs2_.apply(void 0, __spreadArrays(s_, s_, s_)); // error FIXME: worse error message +// fs2n_(...s2, ...s_); // FIXME: should be a type error +fs2n_.apply(void 0, s2_); // error on ...s2_ +// ok +fs2_.apply(void 0, s2_); +fs2_.apply(void 0, __spreadArrays(s2_, s_)); +fs2_.apply(void 0, __spreadArrays(s2_, s2_)); +fs2_.apply(void 0, __spreadArrays(s_, s2_)); +fs2n_.apply(void 0, s2n_); +fs2n_.apply(void 0, s2); +// fs2n_(...s2, ...n_); // FIXME: should compile +fs5.apply(void 0, __spreadArrays(s2, ["foo"], s2)); diff --git a/tests/baselines/reference/callWithSpread3.symbols b/tests/baselines/reference/callWithSpread3.symbols index 3f0ea2d8dd814..e305b1d03ed6d 100644 --- a/tests/baselines/reference/callWithSpread3.symbols +++ b/tests/baselines/reference/callWithSpread3.symbols @@ -1,36 +1,127 @@ === tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts === -declare function takeTwo(a: string, b: string): void; ->takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0)) ->a : Symbol(a, Decl(callWithSpread3.ts, 0, 25)) ->b : Symbol(b, Decl(callWithSpread3.ts, 0, 35)) +declare const s2: [string, string]; +>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13)) -declare const t2: [string, string]; ->t2 : Symbol(t2, Decl(callWithSpread3.ts, 1, 13)) +declare const s3: [string, string, string]; +>s3 : Symbol(s3, Decl(callWithSpread3.ts, 1, 13)) -declare const t3: [string, string, string]; ->t3 : Symbol(t3, Decl(callWithSpread3.ts, 2, 13)) +declare const s2_: [string, string, ...string[]]; +>s2_ : Symbol(s2_, Decl(callWithSpread3.ts, 2, 13)) -takeTwo('a', ...t2); // error on ...t2 ->takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0)) ->t2 : Symbol(t2, Decl(callWithSpread3.ts, 1, 13)) +declare const s_: string[]; +>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13)) -takeTwo('a', 'b', 'c', ...t2); // error on 'c' and ...t2 ->takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0)) ->t2 : Symbol(t2, Decl(callWithSpread3.ts, 1, 13)) +declare const n_: number[]; +>n_ : Symbol(n_, Decl(callWithSpread3.ts, 4, 13)) -takeTwo('a', 'b', ...t2, 'c'); // error on ...t2 and 'c' ->takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0)) ->t2 : Symbol(t2, Decl(callWithSpread3.ts, 1, 13)) +declare const s2n_: [string, string, ...number[]]; +>s2n_ : Symbol(s2n_, Decl(callWithSpread3.ts, 5, 13)) -takeTwo('a', 'b', 'c', ...t2, 'd'); // error on 'c', ...t2 and 'd' ->takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0)) ->t2 : Symbol(t2, Decl(callWithSpread3.ts, 1, 13)) +declare function fs2(a: string, b: string): void; +>fs2 : Symbol(fs2, Decl(callWithSpread3.ts, 5, 50)) +>a : Symbol(a, Decl(callWithSpread3.ts, 7, 21)) +>b : Symbol(b, Decl(callWithSpread3.ts, 7, 31)) -takeTwo(...t2, 'a'); // error on 'a' ->takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0)) ->t2 : Symbol(t2, Decl(callWithSpread3.ts, 1, 13)) +declare function fs2_(a: string, b: string, ...c: string[]): void; +>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49)) +>a : Symbol(a, Decl(callWithSpread3.ts, 8, 22)) +>b : Symbol(b, Decl(callWithSpread3.ts, 8, 32)) +>c : Symbol(c, Decl(callWithSpread3.ts, 8, 43)) -takeTwo(...t3); // error on ...t3 ->takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0)) ->t3 : Symbol(t3, Decl(callWithSpread3.ts, 2, 13)) +declare function fs2n_(a: string, b: string, ...c: number[]): void; +>fs2n_ : Symbol(fs2n_, Decl(callWithSpread3.ts, 8, 66)) +>a : Symbol(a, Decl(callWithSpread3.ts, 9, 23)) +>b : Symbol(b, Decl(callWithSpread3.ts, 9, 33)) +>c : Symbol(c, Decl(callWithSpread3.ts, 9, 44)) + +declare function fs5(a: string, b: string, c: string, d: string, e: string): void; +>fs5 : Symbol(fs5, Decl(callWithSpread3.ts, 9, 67)) +>a : Symbol(a, Decl(callWithSpread3.ts, 10, 21)) +>b : Symbol(b, Decl(callWithSpread3.ts, 10, 31)) +>c : Symbol(c, Decl(callWithSpread3.ts, 10, 42)) +>d : Symbol(d, Decl(callWithSpread3.ts, 10, 53)) +>e : Symbol(e, Decl(callWithSpread3.ts, 10, 64)) + +// error +fs2('a', ...s2); // error on ...s2 +>fs2 : Symbol(fs2, Decl(callWithSpread3.ts, 5, 50)) +>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13)) + +fs2('a', 'b', 'c', ...s2); // error on 'c' and ...s2 +>fs2 : Symbol(fs2, Decl(callWithSpread3.ts, 5, 50)) +>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13)) + +fs2('a', 'b', ...s2, 'c'); // error on ...s2 and 'c' +>fs2 : Symbol(fs2, Decl(callWithSpread3.ts, 5, 50)) +>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13)) + +fs2('a', 'b', 'c', ...s2, 'd'); // error on 'c', ...s2 and 'd' +>fs2 : Symbol(fs2, Decl(callWithSpread3.ts, 5, 50)) +>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13)) + +fs2(...s2, 'a'); // error on 'a' +>fs2 : Symbol(fs2, Decl(callWithSpread3.ts, 5, 50)) +>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13)) + +fs2(...s3); // error on ...s3 +>fs2 : Symbol(fs2, Decl(callWithSpread3.ts, 5, 50)) +>s3 : Symbol(s3, Decl(callWithSpread3.ts, 1, 13)) + +fs2_(...s_); // error on ...s_ +>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49)) +>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13)) + +fs2_(...s2n_); // error on ...s2n_ +>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49)) +>s2n_ : Symbol(s2n_, Decl(callWithSpread3.ts, 5, 13)) + +fs2_(...s_, ...s_); // error FIXME: bad error message +>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49)) +>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13)) +>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13)) + +fs2_(...s_, ...s_, ...s_); // error FIXME: worse error message +>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49)) +>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13)) +>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13)) +>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13)) + +// fs2n_(...s2, ...s_); // FIXME: should be a type error +fs2n_(...s2_); // error on ...s2_ +>fs2n_ : Symbol(fs2n_, Decl(callWithSpread3.ts, 8, 66)) +>s2_ : Symbol(s2_, Decl(callWithSpread3.ts, 2, 13)) + +// ok +fs2_(...s2_); +>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49)) +>s2_ : Symbol(s2_, Decl(callWithSpread3.ts, 2, 13)) + +fs2_(...s2_, ...s_); +>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49)) +>s2_ : Symbol(s2_, Decl(callWithSpread3.ts, 2, 13)) +>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13)) + +fs2_(...s2_, ...s2_); +>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49)) +>s2_ : Symbol(s2_, Decl(callWithSpread3.ts, 2, 13)) +>s2_ : Symbol(s2_, Decl(callWithSpread3.ts, 2, 13)) + +fs2_(...s_, ...s2_); +>fs2_ : Symbol(fs2_, Decl(callWithSpread3.ts, 7, 49)) +>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13)) +>s2_ : Symbol(s2_, Decl(callWithSpread3.ts, 2, 13)) + +fs2n_(...s2n_); +>fs2n_ : Symbol(fs2n_, Decl(callWithSpread3.ts, 8, 66)) +>s2n_ : Symbol(s2n_, Decl(callWithSpread3.ts, 5, 13)) + +fs2n_(...s2); +>fs2n_ : Symbol(fs2n_, Decl(callWithSpread3.ts, 8, 66)) +>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13)) + +// fs2n_(...s2, ...n_); // FIXME: should compile +fs5(...s2, "foo", ...s2); +>fs5 : Symbol(fs5, Decl(callWithSpread3.ts, 9, 67)) +>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13)) +>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13)) diff --git a/tests/baselines/reference/callWithSpread3.types b/tests/baselines/reference/callWithSpread3.types index 5bbb0037774e8..dc7c7b4378772 100644 --- a/tests/baselines/reference/callWithSpread3.types +++ b/tests/baselines/reference/callWithSpread3.types @@ -1,60 +1,183 @@ === tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts === -declare function takeTwo(a: string, b: string): void; ->takeTwo : (a: string, b: string) => void +declare const s2: [string, string]; +>s2 : [string, string] + +declare const s3: [string, string, string]; +>s3 : [string, string, string] + +declare const s2_: [string, string, ...string[]]; +>s2_ : [string, string, ...string[]] + +declare const s_: string[]; +>s_ : string[] + +declare const n_: number[]; +>n_ : number[] + +declare const s2n_: [string, string, ...number[]]; +>s2n_ : [string, string, ...number[]] + +declare function fs2(a: string, b: string): void; +>fs2 : (a: string, b: string) => void >a : string >b : string -declare const t2: [string, string]; ->t2 : [string, string] +declare function fs2_(a: string, b: string, ...c: string[]): void; +>fs2_ : (a: string, b: string, ...c: string[]) => void +>a : string +>b : string +>c : string[] + +declare function fs2n_(a: string, b: string, ...c: number[]): void; +>fs2n_ : (a: string, b: string, ...c: number[]) => void +>a : string +>b : string +>c : number[] -declare const t3: [string, string, string]; ->t3 : [string, string, string] +declare function fs5(a: string, b: string, c: string, d: string, e: string): void; +>fs5 : (a: string, b: string, c: string, d: string, e: string) => void +>a : string +>b : string +>c : string +>d : string +>e : string -takeTwo('a', ...t2); // error on ...t2 ->takeTwo('a', ...t2) : void ->takeTwo : (a: string, b: string) => void +// error +fs2('a', ...s2); // error on ...s2 +>fs2('a', ...s2) : void +>fs2 : (a: string, b: string) => void >'a' : "a" ->...t2 : string ->t2 : [string, string] +>...s2 : string +>s2 : [string, string] -takeTwo('a', 'b', 'c', ...t2); // error on 'c' and ...t2 ->takeTwo('a', 'b', 'c', ...t2) : void ->takeTwo : (a: string, b: string) => void +fs2('a', 'b', 'c', ...s2); // error on 'c' and ...s2 +>fs2('a', 'b', 'c', ...s2) : void +>fs2 : (a: string, b: string) => void >'a' : "a" >'b' : "b" >'c' : "c" ->...t2 : string ->t2 : [string, string] +>...s2 : string +>s2 : [string, string] -takeTwo('a', 'b', ...t2, 'c'); // error on ...t2 and 'c' ->takeTwo('a', 'b', ...t2, 'c') : void ->takeTwo : (a: string, b: string) => void +fs2('a', 'b', ...s2, 'c'); // error on ...s2 and 'c' +>fs2('a', 'b', ...s2, 'c') : void +>fs2 : (a: string, b: string) => void >'a' : "a" >'b' : "b" ->...t2 : string ->t2 : [string, string] +>...s2 : string +>s2 : [string, string] >'c' : "c" -takeTwo('a', 'b', 'c', ...t2, 'd'); // error on 'c', ...t2 and 'd' ->takeTwo('a', 'b', 'c', ...t2, 'd') : void ->takeTwo : (a: string, b: string) => void +fs2('a', 'b', 'c', ...s2, 'd'); // error on 'c', ...s2 and 'd' +>fs2('a', 'b', 'c', ...s2, 'd') : void +>fs2 : (a: string, b: string) => void >'a' : "a" >'b' : "b" >'c' : "c" ->...t2 : string ->t2 : [string, string] +>...s2 : string +>s2 : [string, string] >'d' : "d" -takeTwo(...t2, 'a'); // error on 'a' ->takeTwo(...t2, 'a') : void ->takeTwo : (a: string, b: string) => void ->...t2 : string ->t2 : [string, string] +fs2(...s2, 'a'); // error on 'a' +>fs2(...s2, 'a') : void +>fs2 : (a: string, b: string) => void +>...s2 : string +>s2 : [string, string] >'a' : "a" -takeTwo(...t3); // error on ...t3 ->takeTwo(...t3) : void ->takeTwo : (a: string, b: string) => void ->...t3 : string ->t3 : [string, string, string] +fs2(...s3); // error on ...s3 +>fs2(...s3) : void +>fs2 : (a: string, b: string) => void +>...s3 : string +>s3 : [string, string, string] + +fs2_(...s_); // error on ...s_ +>fs2_(...s_) : void +>fs2_ : (a: string, b: string, ...c: string[]) => void +>...s_ : string +>s_ : string[] + +fs2_(...s2n_); // error on ...s2n_ +>fs2_(...s2n_) : void +>fs2_ : (a: string, b: string, ...c: string[]) => void +>...s2n_ : string | number +>s2n_ : [string, string, ...number[]] + +fs2_(...s_, ...s_); // error FIXME: bad error message +>fs2_(...s_, ...s_) : void +>fs2_ : (a: string, b: string, ...c: string[]) => void +>...s_ : string +>s_ : string[] +>...s_ : string +>s_ : string[] + +fs2_(...s_, ...s_, ...s_); // error FIXME: worse error message +>fs2_(...s_, ...s_, ...s_) : void +>fs2_ : (a: string, b: string, ...c: string[]) => void +>...s_ : string +>s_ : string[] +>...s_ : string +>s_ : string[] +>...s_ : string +>s_ : string[] + +// fs2n_(...s2, ...s_); // FIXME: should be a type error +fs2n_(...s2_); // error on ...s2_ +>fs2n_(...s2_) : void +>fs2n_ : (a: string, b: string, ...c: number[]) => void +>...s2_ : string +>s2_ : [string, string, ...string[]] + +// ok +fs2_(...s2_); +>fs2_(...s2_) : void +>fs2_ : (a: string, b: string, ...c: string[]) => void +>...s2_ : string +>s2_ : [string, string, ...string[]] + +fs2_(...s2_, ...s_); +>fs2_(...s2_, ...s_) : void +>fs2_ : (a: string, b: string, ...c: string[]) => void +>...s2_ : string +>s2_ : [string, string, ...string[]] +>...s_ : string +>s_ : string[] + +fs2_(...s2_, ...s2_); +>fs2_(...s2_, ...s2_) : void +>fs2_ : (a: string, b: string, ...c: string[]) => void +>...s2_ : string +>s2_ : [string, string, ...string[]] +>...s2_ : string +>s2_ : [string, string, ...string[]] + +fs2_(...s_, ...s2_); +>fs2_(...s_, ...s2_) : void +>fs2_ : (a: string, b: string, ...c: string[]) => void +>...s_ : string +>s_ : string[] +>...s2_ : string +>s2_ : [string, string, ...string[]] + +fs2n_(...s2n_); +>fs2n_(...s2n_) : void +>fs2n_ : (a: string, b: string, ...c: number[]) => void +>...s2n_ : string | number +>s2n_ : [string, string, ...number[]] + +fs2n_(...s2); +>fs2n_(...s2) : void +>fs2n_ : (a: string, b: string, ...c: number[]) => void +>...s2 : string +>s2 : [string, string] + +// fs2n_(...s2, ...n_); // FIXME: should compile +fs5(...s2, "foo", ...s2); +>fs5(...s2, "foo", ...s2) : void +>fs5 : (a: string, b: string, c: string, d: string, e: string) => void +>...s2 : string +>s2 : [string, string] +>"foo" : "foo" +>...s2 : string +>s2 : [string, string] diff --git a/tests/baselines/reference/genericRestParameters1.errors.txt b/tests/baselines/reference/genericRestParameters1.errors.txt index cd9e799535bdb..707e86a94dd8f 100644 --- a/tests/baselines/reference/genericRestParameters1.errors.txt +++ b/tests/baselines/reference/genericRestParameters1.errors.txt @@ -1,5 +1,7 @@ -tests/cases/conformance/types/rest/genericRestParameters1.ts(22,11): error TS2556: Expected 3 arguments, but got 1 or more. -tests/cases/conformance/types/rest/genericRestParameters1.ts(31,11): error TS2556: Expected 3 arguments, but got 1 or more. +tests/cases/conformance/types/rest/genericRestParameters1.ts(22,4): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/rest/genericRestParameters1.ts(31,4): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. + Type 'string' is not assignable to type 'number'. tests/cases/conformance/types/rest/genericRestParameters1.ts(135,23): error TS2344: Type 'Function' does not satisfy the constraint '(...args: any) => any'. Type 'Function' provides no match for the signature '(...args: any): any'. tests/cases/conformance/types/rest/genericRestParameters1.ts(164,1): error TS2322: Type '(a: never) => void' is not assignable to type '(...args: any[]) => void'. @@ -29,9 +31,10 @@ tests/cases/conformance/types/rest/genericRestParameters1.ts(164,1): error TS232 f1(42, "hello", ...t1); f1(42, "hello", true, ...t0); f1(ns[0], ns[1], true); - f1(...ns, true); // Error, tuple spread only expanded when last - ~~~~ -!!! error TS2556: Expected 3 arguments, but got 1 or more. + f1(...ns, true); // FIXME: Error, since ...ns is considered as string|number here + ~~~~~ +!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'string' is not assignable to type 'number'. f2(42, "hello", true); f2(t3[0], t3[1], t3[2]); @@ -40,10 +43,10 @@ tests/cases/conformance/types/rest/genericRestParameters1.ts(164,1): error TS232 f2(42, "hello", ...t1); f2(42, "hello", true, ...t0); f2(ns[0], ns[1], true); - f2(...ns, true); // Error, tuple spread only expanded when last - ~~~~ -!!! error TS2556: Expected 3 arguments, but got 1 or more. -!!! related TS6210 tests/cases/conformance/types/rest/genericRestParameters1.ts:2:30: An argument for 'x1' was not provided. + f2(...ns, true); // FIXME: Error, since ...ns is considered as string|number here + ~~~~~ +!!! error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'string' is not assignable to type 'number'. declare function f10(...args: T): T; diff --git a/tests/baselines/reference/genericRestParameters1.js b/tests/baselines/reference/genericRestParameters1.js index eecb906462f30..0e094d0f288fd 100644 --- a/tests/baselines/reference/genericRestParameters1.js +++ b/tests/baselines/reference/genericRestParameters1.js @@ -20,7 +20,7 @@ f1(42, ...t2); f1(42, "hello", ...t1); f1(42, "hello", true, ...t0); f1(ns[0], ns[1], true); -f1(...ns, true); // Error, tuple spread only expanded when last +f1(...ns, true); // FIXME: Error, since ...ns is considered as string|number here f2(42, "hello", true); f2(t3[0], t3[1], t3[2]); @@ -29,7 +29,7 @@ f2(42, ...t2); f2(42, "hello", ...t1); f2(42, "hello", true, ...t0); f2(ns[0], ns[1], true); -f2(...ns, true); // Error, tuple spread only expanded when last +f2(...ns, true); // FIXME: Error, since ...ns is considered as string|number here declare function f10(...args: T): T; @@ -183,7 +183,7 @@ f1.apply(void 0, __spreadArrays([42], t2)); f1.apply(void 0, __spreadArrays([42, "hello"], t1)); f1.apply(void 0, __spreadArrays([42, "hello", true], t0)); f1(ns[0], ns[1], true); -f1.apply(void 0, __spreadArrays(ns, [true])); // Error, tuple spread only expanded when last +f1.apply(void 0, __spreadArrays(ns, [true])); // FIXME: Error, since ...ns is considered as string|number here f2(42, "hello", true); f2(t3[0], t3[1], t3[2]); f2.apply(void 0, t3); @@ -191,7 +191,7 @@ f2.apply(void 0, __spreadArrays([42], t2)); f2.apply(void 0, __spreadArrays([42, "hello"], t1)); f2.apply(void 0, __spreadArrays([42, "hello", true], t0)); f2(ns[0], ns[1], true); -f2.apply(void 0, __spreadArrays(ns, [true])); // Error, tuple spread only expanded when last +f2.apply(void 0, __spreadArrays(ns, [true])); // FIXME: Error, since ...ns is considered as string|number here var x10 = f10(42, "hello", true); // [number, string, boolean] var x11 = f10(42, "hello"); // [number, string] var x12 = f10(42); // [number] diff --git a/tests/baselines/reference/genericRestParameters1.symbols b/tests/baselines/reference/genericRestParameters1.symbols index 4b0dae5115006..56f1bc6cf5869 100644 --- a/tests/baselines/reference/genericRestParameters1.symbols +++ b/tests/baselines/reference/genericRestParameters1.symbols @@ -70,7 +70,7 @@ f1(ns[0], ns[1], true); >ns : Symbol(ns, Decl(genericRestParameters1.ts, 11, 13)) >1 : Symbol(1) -f1(...ns, true); // Error, tuple spread only expanded when last +f1(...ns, true); // FIXME: Error, since ...ns is considered as string|number here >f1 : Symbol(f1, Decl(genericRestParameters1.ts, 0, 11)) >ns : Symbol(ns, Decl(genericRestParameters1.ts, 11, 13)) @@ -109,7 +109,7 @@ f2(ns[0], ns[1], true); >ns : Symbol(ns, Decl(genericRestParameters1.ts, 11, 13)) >1 : Symbol(1) -f2(...ns, true); // Error, tuple spread only expanded when last +f2(...ns, true); // FIXME: Error, since ...ns is considered as string|number here >f2 : Symbol(f2, Decl(genericRestParameters1.ts, 1, 11)) >ns : Symbol(ns, Decl(genericRestParameters1.ts, 11, 13)) diff --git a/tests/baselines/reference/genericRestParameters1.types b/tests/baselines/reference/genericRestParameters1.types index 1503f11845964..6dfee15241288 100644 --- a/tests/baselines/reference/genericRestParameters1.types +++ b/tests/baselines/reference/genericRestParameters1.types @@ -98,7 +98,7 @@ f1(ns[0], ns[1], true); >1 : 1 >true : true -f1(...ns, true); // Error, tuple spread only expanded when last +f1(...ns, true); // FIXME: Error, since ...ns is considered as string|number here >f1(...ns, true) : void >f1 : (x_0: number, x_1: string, x_2: boolean) => void >...ns : string | number @@ -166,7 +166,7 @@ f2(ns[0], ns[1], true); >1 : 1 >true : true -f2(...ns, true); // Error, tuple spread only expanded when last +f2(...ns, true); // FIXME: Error, since ...ns is considered as string|number here >f2(...ns, true) : void >f2 : (x0: number, x1: string, x2: boolean) => void >...ns : string | number diff --git a/tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts b/tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts index bc5d8c2246fa8..88f9af46df5a4 100644 --- a/tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts +++ b/tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts @@ -1,10 +1,35 @@ -declare function takeTwo(a: string, b: string): void; -declare const t2: [string, string]; -declare const t3: [string, string, string]; +declare const s2: [string, string]; +declare const s3: [string, string, string]; +declare const s2_: [string, string, ...string[]]; +declare const s_: string[]; +declare const n_: number[]; +declare const s2n_: [string, string, ...number[]]; -takeTwo('a', ...t2); // error on ...t2 -takeTwo('a', 'b', 'c', ...t2); // error on 'c' and ...t2 -takeTwo('a', 'b', ...t2, 'c'); // error on ...t2 and 'c' -takeTwo('a', 'b', 'c', ...t2, 'd'); // error on 'c', ...t2 and 'd' -takeTwo(...t2, 'a'); // error on 'a' -takeTwo(...t3); // error on ...t3 \ No newline at end of file +declare function fs2(a: string, b: string): void; +declare function fs2_(a: string, b: string, ...c: string[]): void; +declare function fs2n_(a: string, b: string, ...c: number[]): void; +declare function fs5(a: string, b: string, c: string, d: string, e: string): void; + +// error +fs2('a', ...s2); // error on ...s2 +fs2('a', 'b', 'c', ...s2); // error on 'c' and ...s2 +fs2('a', 'b', ...s2, 'c'); // error on ...s2 and 'c' +fs2('a', 'b', 'c', ...s2, 'd'); // error on 'c', ...s2 and 'd' +fs2(...s2, 'a'); // error on 'a' +fs2(...s3); // error on ...s3 +fs2_(...s_); // error on ...s_ +fs2_(...s2n_); // error on ...s2n_ +fs2_(...s_, ...s_); // error FIXME: bad error message +fs2_(...s_, ...s_, ...s_); // error FIXME: worse error message +// fs2n_(...s2, ...s_); // FIXME: should be a type error +fs2n_(...s2_); // error on ...s2_ + +// ok +fs2_(...s2_); +fs2_(...s2_, ...s_); +fs2_(...s2_, ...s2_); +fs2_(...s_, ...s2_); +fs2n_(...s2n_); +fs2n_(...s2); +// fs2n_(...s2, ...n_); // FIXME: should compile +fs5(...s2, "foo", ...s2); diff --git a/tests/cases/conformance/types/rest/genericRestParameters1.ts b/tests/cases/conformance/types/rest/genericRestParameters1.ts index 6572512cbfbe3..ede07b0d9ac58 100644 --- a/tests/cases/conformance/types/rest/genericRestParameters1.ts +++ b/tests/cases/conformance/types/rest/genericRestParameters1.ts @@ -22,7 +22,7 @@ f1(42, ...t2); f1(42, "hello", ...t1); f1(42, "hello", true, ...t0); f1(ns[0], ns[1], true); -f1(...ns, true); // Error, tuple spread only expanded when last +f1(...ns, true); // FIXME: Error, since ...ns is considered as string|number here f2(42, "hello", true); f2(t3[0], t3[1], t3[2]); @@ -31,7 +31,7 @@ f2(42, ...t2); f2(42, "hello", ...t1); f2(42, "hello", true, ...t0); f2(ns[0], ns[1], true); -f2(...ns, true); // Error, tuple spread only expanded when last +f2(...ns, true); // FIXME: Error, since ...ns is considered as string|number here declare function f10(...args: T): T;