diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 682a1e7435fa5..c4163a1f68f6b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28411,7 +28411,7 @@ namespace ts { /** * Returns the effective arguments for an expression that works like a function invocation. */ - function getEffectiveCallArguments(node: CallLikeExpression): readonly Expression[] { + function getEffectiveCallArguments(node: CallLikeExpression, signatures?: readonly Signature[]): readonly Expression[] { if (node.kind === SyntaxKind.TaggedTemplateExpression) { const template = node.template; const args: Expression[] = [createSyntheticExpression(template, getGlobalTemplateStringsArrayType())]; @@ -28436,14 +28436,62 @@ namespace ts { for (let i = spreadIndex; i < args.length; i++) { const arg = args[i]; // We can call checkExpressionCached because spread expressions never have a contextual type. - const spreadType = arg.kind === SyntaxKind.SpreadElement && (flowLoopCount ? checkExpression((arg).expression) : checkExpressionCached((arg).expression)); - if (spreadType && isTupleType(spreadType)) { - forEach(getTypeArguments(spreadType), (t, i) => { - const flags = spreadType.target.elementFlags[i]; - const syntheticArg = createSyntheticExpression(arg, flags & ElementFlags.Rest ? createArrayType(t) : t, - !!(flags & ElementFlags.Variable), spreadType.target.labeledElementDeclarations?.[i]); - effectiveArgs.push(syntheticArg); - }); + const spreadType = arg.kind === SyntaxKind.SpreadElement && + (flowLoopCount ? checkExpression((arg).expression) : checkExpressionCached((arg).expression)); + if (spreadType && everyType(spreadType, isTupleType)) { + if (spreadType.flags & TypeFlags.Union) { + // TODO: Don't do this if there's a matching rest parameter that also has a tuple-union type + let tmp = [] + const types = (spreadType as UnionType).types + const typess = types.map(getTypeArguments) + const longest = Math.max(...typess.map(ts => ts.length)) + for (let j = 0; j < longest; j++) { + // TODO: Having undefined in the type now includes optionality (but maybe should *only* be optional) (and maybe shouldn't be???) + const t = getUnionType(typess.map(ts => ts[j] || undefinedType)) + const flags: ElementFlags = types.map(t => (t as TupleTypeReference).target.elementFlags[j] || ElementFlags.Optional).reduce((total,f) => f | total, 0) + // TODO: bail if flags aren't ElementFlags.Fixed (it might be OK to allow a rest at the end, but calculating the 'end' is a draaaaaaaag) + if (flags & ~ElementFlags.Fixed) { + tmp = [arg] + break + + } + // TODO: Not sure at all what to do with labels, but there might be some utilities for this already + const syntheticArg = createSyntheticExpression(arg, t); + tmp.push(syntheticArg) + } + effectiveArgs.push(...tmp) + } + else { + forEach(getTypeArguments(spreadType as TupleTypeReference), (t, i) => { + const flags = (spreadType as TupleTypeReference).target.elementFlags[i]; + const syntheticArg = createSyntheticExpression( + arg, + flags & ElementFlags.Rest ? createArrayType(t) : t, + !!(flags & ElementFlags.Variable), + (spreadType as TupleTypeReference).target.labeledElementDeclarations?.[i]); + effectiveArgs.push(syntheticArg); + }); + } + } + else if (spreadType && signatures?.length === 1 && signatures[0].declaration && isArrayType(spreadType)) { + // convert T[] into [T?, T?, T?, T], for as many as there are parameters after this spread + // TODO: Don't do this if there's a matching rest parameter (checking all signatures[effectiveArgs.length] might do the trick?) + const params = signatures[0].parameters + const last = lastOrUndefined(signatures[0].declaration.parameters); + if (!!last && isRestParameter(last) && i !== params.length - 1) { + const t = getElementTypeOfArrayType(spreadType)! + for (let j = 0; j < params.length - i - 1; j++) { + // TODO: This loosens checking of spreads dramatically without strict null checks + // It assumes that a spread is always long enough + // Test the prototype without strict null checks, but only ship under that flag. + effectiveArgs.push(createSyntheticExpression(arg, getUnionType([t, undefinedType]))) + } + // TODO: The -1 doesn't check that an overlong array is still assignable, so push a non-undefined type on the end + effectiveArgs.push(createSyntheticExpression(arg, t)) + } + else { + effectiveArgs.push(arg); + } } else { effectiveArgs.push(arg); @@ -28559,88 +28607,67 @@ namespace ts { } function getArgumentArityError(node: CallLikeExpression, signatures: readonly Signature[], args: readonly Expression[]) { - let min = Number.POSITIVE_INFINITY; - let max = Number.NEGATIVE_INFINITY; - let belowArgCount = Number.NEGATIVE_INFINITY; - let aboveArgCount = Number.POSITIVE_INFINITY; + const spreadIndex = getSpreadArgumentIndex(args); + if (spreadIndex > -1) { + return createDiagnosticForNode(args[spreadIndex], Diagnostics.A_spread_must_either_have_a_tuple_type_or_be_passed_to_a_rest_parameter); + } + let min = Number.POSITIVE_INFINITY; // smallest parameter count + let max = Number.NEGATIVE_INFINITY; // larger parameter count + let maxBelow = Number.NEGATIVE_INFINITY; // largest parameter count that is smaller than the number of arguments + let minAbove = Number.POSITIVE_INFINITY; // smallest parameter count that is larger than the number of arguments - let argCount = args.length; let closestSignature: Signature | undefined; for (const sig of signatures) { - const minCount = getMinArgumentCount(sig); - const maxCount = getParameterCount(sig); - if (minCount < argCount && minCount > belowArgCount) belowArgCount = minCount; - if (argCount < maxCount && maxCount < aboveArgCount) aboveArgCount = maxCount; - if (minCount < min) { - min = minCount; + const minParameter = getMinArgumentCount(sig); + const maxParameter = getParameterCount(sig); + // shortest/longest parameter counts + if (minParameter < min) { + min = minParameter; closestSignature = sig; } - max = Math.max(max, maxCount); - } - - if (min < argCount && argCount < max) { - return getDiagnosticForCallNode(node, Diagnostics.No_overload_expects_0_arguments_but_overloads_do_exist_that_expect_either_1_or_2_arguments, argCount, belowArgCount, aboveArgCount); + max = Math.max(max, maxParameter); + // shortest parameter count *longer than the call*/longest parameter count *shorter than the call* + if (minParameter < args.length && minParameter > maxBelow) maxBelow = minParameter; + if (args.length < maxParameter && maxParameter < minAbove) minAbove = maxParameter; } - const hasRestParameter = some(signatures, hasEffectiveRestParameter); - const paramRange = hasRestParameter ? min : - min < max ? min + "-" + max : - min; - const hasSpreadArgument = getSpreadArgumentIndex(args) > -1; - if (argCount <= max && hasSpreadArgument) { - argCount--; - } - - let spanArray: NodeArray; - let related: DiagnosticWithLocation | undefined; - - const error = hasRestParameter || hasSpreadArgument ? - hasRestParameter && hasSpreadArgument ? - Diagnostics.Expected_at_least_0_arguments_but_got_1_or_more : - hasRestParameter ? - Diagnostics.Expected_at_least_0_arguments_but_got_1 : - Diagnostics.Expected_0_arguments_but_got_1_or_more : - paramRange === 1 && argCount === 0 && isPromiseResolveArityError(node) ? - Diagnostics.Expected_0_arguments_but_got_1_Did_you_forget_to_include_void_in_your_type_argument_to_Promise : - Diagnostics.Expected_0_arguments_but_got_1; - - if (closestSignature && getMinArgumentCount(closestSignature) > argCount && closestSignature.declaration) { - const paramDecl = closestSignature.declaration.parameters[closestSignature.thisParameter ? argCount + 1 : argCount]; - if (paramDecl) { - related = createDiagnosticForNode( - paramDecl, - isBindingPattern(paramDecl.name) ? Diagnostics.An_argument_matching_this_binding_pattern_was_not_provided : - isRestParameter(paramDecl) ? Diagnostics.Arguments_for_the_rest_parameter_0_were_not_provided : Diagnostics.An_argument_for_0_was_not_provided, - !paramDecl.name ? argCount : !isBindingPattern(paramDecl.name) ? idText(getFirstIdentifier(paramDecl.name)) : undefined + const parameterRange = hasRestParameter ? min + : min < max ? min + "-" + max + : min; + const error = hasRestParameter ? Diagnostics.Expected_at_least_0_arguments_but_got_1 + : parameterRange === 1 && args.length === 0 && isPromiseResolveArityError(node) ? Diagnostics.Expected_0_arguments_but_got_1_Did_you_forget_to_include_void_in_your_type_argument_to_Promise + : Diagnostics.Expected_0_arguments_but_got_1; + if (min < args.length && args.length < max) { + // between min and max, but with no matching overload + return getDiagnosticForCallNode(node, Diagnostics.No_overload_expects_0_arguments_but_overloads_do_exist_that_expect_either_1_or_2_arguments, args.length, maxBelow, minAbove); + } + else if (args.length < min) { + // too short: put the error span on the call expression, not any of the args + const diagnostic = getDiagnosticForCallNode(node, error, parameterRange, args.length); + const parameter = closestSignature?.declaration?.parameters[closestSignature.thisParameter ? args.length + 1 : args.length]; + if (parameter) { + const parameterError = createDiagnosticForNode( + parameter, + isBindingPattern(parameter.name) ? Diagnostics.An_argument_matching_this_binding_pattern_was_not_provided + : isRestParameter(parameter) ? Diagnostics.Arguments_for_the_rest_parameter_0_were_not_provided + : Diagnostics.An_argument_for_0_was_not_provided, + !parameter.name ? args.length : !isBindingPattern(parameter.name) ? idText(getFirstIdentifier(parameter.name)) : undefined ); + return addRelatedInfo(diagnostic, parameterError); } - } - - if (!hasSpreadArgument && argCount < min) { - const diagnostic = getDiagnosticForCallNode(node, error, paramRange, argCount); - return related ? addRelatedInfo(diagnostic, related) : diagnostic; - } - - if (hasRestParameter || hasSpreadArgument) { - spanArray = factory.createNodeArray(args); - if (hasSpreadArgument && argCount) { - const nextArg = elementAt(args, getSpreadArgumentIndex(args) + 1) || undefined; - spanArray = factory.createNodeArray(args.slice(max > argCount && nextArg ? args.indexOf(nextArg) : Math.min(max, args.length - 1))); - } + return diagnostic; } else { - spanArray = factory.createNodeArray(args.slice(max)); - } - - const pos = first(spanArray).pos; - let end = last(spanArray).end; - if (end === pos) { - end++; + // too long; error goes on the excess parameters + const errorSpan = factory.createNodeArray(args.slice(max)); + const pos = first(errorSpan).pos; + let end = last(errorSpan).end; + if (end === pos) { + end++; + } + setTextRangePosEnd(errorSpan, pos, end); + return createDiagnosticForNodeArray(getSourceFileOfNode(node), errorSpan, error, parameterRange, args.length); } - setTextRangePosEnd(spanArray, pos, end); - const diagnostic = createDiagnosticForNodeArray( - getSourceFileOfNode(node), spanArray, error, paramRange, argCount); - return related ? addRelatedInfo(diagnostic, related) : diagnostic; } function getTypeArgumentArityError(node: Node, signatures: readonly Signature[], typeArguments: NodeArray) { @@ -28698,7 +28725,7 @@ namespace ts { return resolveErrorCall(node); } - const args = getEffectiveCallArguments(node); + const args = getEffectiveCallArguments(node, signatures); // The excludeArgument array contains true for each context sensitive argument (an argument // is context sensitive it is susceptible to a one-time permanent contextual typing). diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 8828ae051c56b..3e9985b4d1da1 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -526,7 +526,7 @@ "'extends' clause already seen.": { "category": "Error", "code": 1172 - }, + }, "'extends' clause must precede 'implements' clause.": { "category": "Error", "code": 1173 @@ -2386,14 +2386,10 @@ "category": "Error", "code": 2555 }, - "Expected {0} arguments, but got {1} or more.": { + "A spread must either have a tuple type or be passed to a rest parameter.": { "category": "Error", "code": 2556 }, - "Expected at least {0} arguments, but got {1} or more.": { - "category": "Error", - "code": 2557 - }, "Expected {0} type arguments, but got {1}.": { "category": "Error", "code": 2558 diff --git a/tests/baselines/reference/callOverload.errors.txt b/tests/baselines/reference/callOverload.errors.txt index 0f6a2ade085a0..b9edb3801a14b 100644 --- a/tests/baselines/reference/callOverload.errors.txt +++ b/tests/baselines/reference/callOverload.errors.txt @@ -1,10 +1,9 @@ tests/cases/conformance/expressions/functionCalls/callOverload.ts(7,7): error TS2554: Expected 1 arguments, but got 4. tests/cases/conformance/expressions/functionCalls/callOverload.ts(8,15): error TS2554: Expected 2 arguments, but got 4. tests/cases/conformance/expressions/functionCalls/callOverload.ts(10,1): error TS2555: Expected at least 1 arguments, but got 0. -tests/cases/conformance/expressions/functionCalls/callOverload.ts(11,10): error TS2557: Expected at least 1 arguments, but got 0 or more. -==== tests/cases/conformance/expressions/functionCalls/callOverload.ts (4 errors) ==== +==== tests/cases/conformance/expressions/functionCalls/callOverload.ts (3 errors) ==== declare function fn(x: any): void; declare function takeTwo(x: any, y: any): void; declare function withRest(a: any, ...args: Array): void; @@ -22,7 +21,4 @@ tests/cases/conformance/expressions/functionCalls/callOverload.ts(11,10): error ~~~~~~~~~~ !!! error TS2555: Expected at least 1 arguments, but got 0. !!! related TS6210 tests/cases/conformance/expressions/functionCalls/callOverload.ts:3:27: An argument for 'a' was not provided. - withRest(...n); - ~~~~ -!!! error TS2557: Expected at least 1 arguments, but got 0 or more. -!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callOverload.ts:3:27: An argument for 'a' was not provided. \ No newline at end of file + withRest(...n); \ No newline at end of file diff --git a/tests/baselines/reference/callWithSpread2.errors.txt b/tests/baselines/reference/callWithSpread2.errors.txt index 080c229e6042e..863147032b944 100644 --- a/tests/baselines/reference/callWithSpread2.errors.txt +++ b/tests/baselines/reference/callWithSpread2.errors.txt @@ -1,5 +1,5 @@ -tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(23,13): error TS2556: Expected 1 arguments, but got 2 or more. -tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(24,7): error TS2556: Expected 0 arguments, but got 1 or more. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(23,13): error TS2556: A spread must either have a tuple type or be passed to a rest parameter. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(24,7): error TS2556: A spread must either have a tuple type or be passed to a rest parameter. tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(27,5): 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/expressions/functionCalls/callWithSpread2.ts(28,5): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. @@ -9,10 +9,10 @@ tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(30,13): err tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(31,11): 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/expressions/functionCalls/callWithSpread2.ts(32,11): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. -tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(33,8): error TS2556: Expected 1-3 arguments, but got 0 or more. -tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(34,8): error TS2556: Expected 1-3 arguments, but got 0 or more. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(33,8): error TS2556: A spread must either have a tuple type or be passed to a rest parameter. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(34,8): error TS2556: A spread must either have a tuple type or be passed to a rest parameter. tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(35,8): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. -tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(36,14): error TS2556: Expected 2-4 arguments, but got 1 or more. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(36,14): error TS2556: A spread must either have a tuple type or be passed to a rest parameter. ==== tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts (12 errors) ==== @@ -40,10 +40,10 @@ tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(36,14): err // extra arguments normal("g", ...ns) ~~~~~ -!!! error TS2556: Expected 1 arguments, but got 2 or more. +!!! error TS2556: A spread must either have a tuple type or be passed to a rest parameter. thunk(...ns) ~~~~~ -!!! error TS2556: Expected 0 arguments, but got 1 or more. +!!! error TS2556: A spread must either have a tuple type or be passed to a rest parameter. // bad all(...mixed) @@ -69,17 +69,14 @@ tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(36,14): err !!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. prefix(...ns) // required parameters are required ~~~~~ -!!! error TS2556: Expected 1-3 arguments, but got 0 or more. -!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts:3:25: An argument for 's' was not provided. +!!! error TS2556: A spread must either have a tuple type or be passed to a rest parameter. prefix(...mixed) ~~~~~~~~ -!!! error TS2556: Expected 1-3 arguments, but got 0 or more. -!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts:3:25: An argument for 's' was not provided. +!!! error TS2556: A spread must either have a tuple type or be passed to a rest parameter. prefix(...tuple) ~~~~~~~~ !!! error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'. prefix2("g", ...ns); ~~~~~ -!!! error TS2556: Expected 2-4 arguments, but got 1 or more. -!!! related TS6210 tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts:7:37: An argument for 'n' was not provided. +!!! error TS2556: A spread must either have a tuple type or be passed to a rest parameter. \ No newline at end of file diff --git a/tests/baselines/reference/callWithSpread3.errors.txt b/tests/baselines/reference/callWithSpread3.errors.txt index 062c273a26a9c..489f79a32d993 100644 --- a/tests/baselines/reference/callWithSpread3.errors.txt +++ b/tests/baselines/reference/callWithSpread3.errors.txt @@ -4,15 +4,12 @@ tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(16,15): err tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(17,15): error TS2554: Expected 2 arguments, but got 6. tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(18,12): error TS2554: Expected 2 arguments, but got 3. 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(24,14): error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. 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(31,13): error TS2557: Expected at least 2 arguments, but got 4 or more. -==== tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts (12 errors) ==== +==== tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts (9 errors) ==== declare const s2: [string, string]; declare const s3: [string, string, string]; declare const s2_: [string, string, ...string[]]; @@ -45,20 +42,14 @@ tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(31,13): err ~~~~~ !!! 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, ...s_); // FIXME: should be a type error + ~~~~~ +!!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. fs2n_(...s2_); // error on ...s2_ ~~~~~~ !!! error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'. @@ -68,10 +59,8 @@ tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(31,13): err fs2_(...s2_, ...s_); fs2_(...s2_, ...s2_); fs2_(...s_, ...s2_); - ~~~~~~ -!!! error TS2557: Expected at least 2 arguments, but got 4 or more. fs2n_(...s2n_); fs2n_(...s2); - // fs2n_(...s2, ...n_); // FIXME: should compile + 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 f94e74b1dd434..655102517893e 100644 --- a/tests/baselines/reference/callWithSpread3.js +++ b/tests/baselines/reference/callWithSpread3.js @@ -22,7 +22,7 @@ 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, ...s_); // FIXME: should be a type error fs2n_(...s2_); // error on ...s2_ // ok @@ -32,7 +32,7 @@ fs2_(...s2_, ...s2_); fs2_(...s_, ...s2_); fs2n_(...s2n_); fs2n_(...s2); -// fs2n_(...s2, ...n_); // FIXME: should compile +fs2n_(...s2, ...n_); // FIXME: should compile fs5(...s2, "foo", ...s2); @@ -53,7 +53,7 @@ fs2_.apply(void 0, s_); // error on ...s_ fs2_.apply(void 0, s2n_); // error on ...s2n_ fs2_.apply(void 0, __spreadArray(__spreadArray([], s_), s_)); // error FIXME: bad error message fs2_.apply(void 0, __spreadArray(__spreadArray(__spreadArray([], s_), s_), s_)); // error FIXME: worse error message -// fs2n_(...s2, ...s_); // FIXME: should be a type error +fs2n_.apply(void 0, __spreadArray(__spreadArray([], s2), s_)); // FIXME: should be a type error fs2n_.apply(void 0, s2_); // error on ...s2_ // ok fs2_.apply(void 0, s2_); @@ -62,5 +62,5 @@ fs2_.apply(void 0, __spreadArray(__spreadArray([], s2_), s2_)); fs2_.apply(void 0, __spreadArray(__spreadArray([], s_), s2_)); fs2n_.apply(void 0, s2n_); fs2n_.apply(void 0, s2); -// fs2n_(...s2, ...n_); // FIXME: should compile +fs2n_.apply(void 0, __spreadArray(__spreadArray([], s2), n_)); // FIXME: should compile fs5.apply(void 0, __spreadArray(__spreadArray(__spreadArray([], s2), ["foo"]), s2)); diff --git a/tests/baselines/reference/callWithSpread3.symbols b/tests/baselines/reference/callWithSpread3.symbols index e305b1d03ed6d..8f75dfd8d0c63 100644 --- a/tests/baselines/reference/callWithSpread3.symbols +++ b/tests/baselines/reference/callWithSpread3.symbols @@ -86,7 +86,11 @@ fs2_(...s_, ...s_, ...s_); // error FIXME: worse error message >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, ...s_); // FIXME: should be a type error +>fs2n_ : Symbol(fs2n_, Decl(callWithSpread3.ts, 8, 66)) +>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13)) +>s_ : Symbol(s_, Decl(callWithSpread3.ts, 3, 13)) + fs2n_(...s2_); // error on ...s2_ >fs2n_ : Symbol(fs2n_, Decl(callWithSpread3.ts, 8, 66)) >s2_ : Symbol(s2_, Decl(callWithSpread3.ts, 2, 13)) @@ -119,7 +123,11 @@ fs2n_(...s2); >fs2n_ : Symbol(fs2n_, Decl(callWithSpread3.ts, 8, 66)) >s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13)) -// fs2n_(...s2, ...n_); // FIXME: should compile +fs2n_(...s2, ...n_); // FIXME: should compile +>fs2n_ : Symbol(fs2n_, Decl(callWithSpread3.ts, 8, 66)) +>s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13)) +>n_ : Symbol(n_, Decl(callWithSpread3.ts, 4, 13)) + fs5(...s2, "foo", ...s2); >fs5 : Symbol(fs5, Decl(callWithSpread3.ts, 9, 67)) >s2 : Symbol(s2, Decl(callWithSpread3.ts, 0, 13)) diff --git a/tests/baselines/reference/callWithSpread3.types b/tests/baselines/reference/callWithSpread3.types index dc7c7b4378772..94be315d370d4 100644 --- a/tests/baselines/reference/callWithSpread3.types +++ b/tests/baselines/reference/callWithSpread3.types @@ -121,7 +121,14 @@ fs2_(...s_, ...s_, ...s_); // error FIXME: worse error message >...s_ : string >s_ : string[] -// fs2n_(...s2, ...s_); // FIXME: should be a type error +fs2n_(...s2, ...s_); // FIXME: should be a type error +>fs2n_(...s2, ...s_) : void +>fs2n_ : (a: string, b: string, ...c: number[]) => void +>...s2 : string +>s2 : [string, string] +>...s_ : string +>s_ : string[] + fs2n_(...s2_); // error on ...s2_ >fs2n_(...s2_) : void >fs2n_ : (a: string, b: string, ...c: number[]) => void @@ -171,7 +178,14 @@ fs2n_(...s2); >...s2 : string >s2 : [string, string] -// fs2n_(...s2, ...n_); // FIXME: should compile +fs2n_(...s2, ...n_); // FIXME: should compile +>fs2n_(...s2, ...n_) : void +>fs2n_ : (a: string, b: string, ...c: number[]) => void +>...s2 : string +>s2 : [string, string] +>...n_ : number +>n_ : number[] + fs5(...s2, "foo", ...s2); >fs5(...s2, "foo", ...s2) : void >fs5 : (a: string, b: string, c: string, d: string, e: string) => void diff --git a/tests/baselines/reference/callWithSpread4.errors.txt b/tests/baselines/reference/callWithSpread4.errors.txt new file mode 100644 index 0000000000000..a50d757dac4fd --- /dev/null +++ b/tests/baselines/reference/callWithSpread4.errors.txt @@ -0,0 +1,39 @@ +tests/cases/conformance/expressions/functionCalls/callWithSpread4.ts(18,5): error TS2556: A spread must either have a tuple type or be passed to a rest parameter. +tests/cases/conformance/expressions/functionCalls/callWithSpread4.ts(27,6): error TS2556: A spread must either have a tuple type or be passed to a rest parameter. + + +==== tests/cases/conformance/expressions/functionCalls/callWithSpread4.ts (2 errors) ==== + type R = { a: number } + type W = { b: number } + type RW = { a: number, b: number } + declare const pli: { + (s1: R, s2: RW, s3: RW, s4: RW, s5: W): Promise; + (streams: ReadonlyArray): Promise; + (s1: R, s2: RW | W, ...streams: Array): Promise; + } + + declare var writes: W + declare var reads: R + declare var tr: W + declare var gun: RW[] + declare var gz: RW[] + declare var fun: (inp: any) => AsyncGenerator + pli( + reads, + ...gun, + ~~~~~~ +!!! error TS2556: A spread must either have a tuple type or be passed to a rest parameter. + tr, + fun, + ...gz, + writes + ); + + declare function test(x: any, y: () => string): string | undefined; + declare var anys: any[] + test(...anys) + ~~~~~~~ +!!! error TS2556: A spread must either have a tuple type or be passed to a rest parameter. + + pli(...[reads, writes, writes] as const) + \ No newline at end of file diff --git a/tests/baselines/reference/callWithSpread4.js b/tests/baselines/reference/callWithSpread4.js new file mode 100644 index 0000000000000..0db1129c0bb11 --- /dev/null +++ b/tests/baselines/reference/callWithSpread4.js @@ -0,0 +1,37 @@ +//// [callWithSpread4.ts] +type R = { a: number } +type W = { b: number } +type RW = { a: number, b: number } +declare const pli: { + (s1: R, s2: RW, s3: RW, s4: RW, s5: W): Promise; + (streams: ReadonlyArray): Promise; + (s1: R, s2: RW | W, ...streams: Array): Promise; +} + +declare var writes: W +declare var reads: R +declare var tr: W +declare var gun: RW[] +declare var gz: RW[] +declare var fun: (inp: any) => AsyncGenerator +pli( + reads, + ...gun, + tr, + fun, + ...gz, + writes +); + +declare function test(x: any, y: () => string): string | undefined; +declare var anys: any[] +test(...anys) + +pli(...[reads, writes, writes] as const) + + +//// [callWithSpread4.js] +"use strict"; +pli(reads, ...gun, tr, fun, ...gz, writes); +test(...anys); +pli(...[reads, writes, writes]); diff --git a/tests/baselines/reference/callWithSpread4.symbols b/tests/baselines/reference/callWithSpread4.symbols new file mode 100644 index 0000000000000..5c3e96596ef60 --- /dev/null +++ b/tests/baselines/reference/callWithSpread4.symbols @@ -0,0 +1,117 @@ +=== tests/cases/conformance/expressions/functionCalls/callWithSpread4.ts === +type R = { a: number } +>R : Symbol(R, Decl(callWithSpread4.ts, 0, 0)) +>a : Symbol(a, Decl(callWithSpread4.ts, 0, 10)) + +type W = { b: number } +>W : Symbol(W, Decl(callWithSpread4.ts, 0, 22)) +>b : Symbol(b, Decl(callWithSpread4.ts, 1, 10)) + +type RW = { a: number, b: number } +>RW : Symbol(RW, Decl(callWithSpread4.ts, 1, 22)) +>a : Symbol(a, Decl(callWithSpread4.ts, 2, 11)) +>b : Symbol(b, Decl(callWithSpread4.ts, 2, 22)) + +declare const pli: { +>pli : Symbol(pli, Decl(callWithSpread4.ts, 3, 13)) + + (s1: R, s2: RW, s3: RW, s4: RW, s5: W): Promise; +>s1 : Symbol(s1, Decl(callWithSpread4.ts, 4, 5)) +>R : Symbol(R, Decl(callWithSpread4.ts, 0, 0)) +>s2 : Symbol(s2, Decl(callWithSpread4.ts, 4, 11)) +>RW : Symbol(RW, Decl(callWithSpread4.ts, 1, 22)) +>s3 : Symbol(s3, Decl(callWithSpread4.ts, 4, 19)) +>RW : Symbol(RW, Decl(callWithSpread4.ts, 1, 22)) +>s4 : Symbol(s4, Decl(callWithSpread4.ts, 4, 27)) +>RW : Symbol(RW, Decl(callWithSpread4.ts, 1, 22)) +>s5 : Symbol(s5, Decl(callWithSpread4.ts, 4, 35)) +>W : Symbol(W, Decl(callWithSpread4.ts, 0, 22)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) + + (streams: ReadonlyArray): Promise; +>streams : Symbol(streams, Decl(callWithSpread4.ts, 5, 5)) +>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2016.array.include.d.ts, --, --), Decl(lib.es2019.array.d.ts, --, --)) +>R : Symbol(R, Decl(callWithSpread4.ts, 0, 0)) +>W : Symbol(W, Decl(callWithSpread4.ts, 0, 22)) +>RW : Symbol(RW, Decl(callWithSpread4.ts, 1, 22)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) + + (s1: R, s2: RW | W, ...streams: Array): Promise; +>s1 : Symbol(s1, Decl(callWithSpread4.ts, 6, 5)) +>R : Symbol(R, Decl(callWithSpread4.ts, 0, 0)) +>s2 : Symbol(s2, Decl(callWithSpread4.ts, 6, 11)) +>RW : Symbol(RW, Decl(callWithSpread4.ts, 1, 22)) +>W : Symbol(W, Decl(callWithSpread4.ts, 0, 22)) +>streams : Symbol(streams, Decl(callWithSpread4.ts, 6, 23)) +>Array : Symbol(Array, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.core.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --) ... and 2 more) +>RW : Symbol(RW, Decl(callWithSpread4.ts, 1, 22)) +>W : Symbol(W, Decl(callWithSpread4.ts, 0, 22)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --)) +} + +declare var writes: W +>writes : Symbol(writes, Decl(callWithSpread4.ts, 9, 11)) +>W : Symbol(W, Decl(callWithSpread4.ts, 0, 22)) + +declare var reads: R +>reads : Symbol(reads, Decl(callWithSpread4.ts, 10, 11)) +>R : Symbol(R, Decl(callWithSpread4.ts, 0, 0)) + +declare var tr: W +>tr : Symbol(tr, Decl(callWithSpread4.ts, 11, 11)) +>W : Symbol(W, Decl(callWithSpread4.ts, 0, 22)) + +declare var gun: RW[] +>gun : Symbol(gun, Decl(callWithSpread4.ts, 12, 11)) +>RW : Symbol(RW, Decl(callWithSpread4.ts, 1, 22)) + +declare var gz: RW[] +>gz : Symbol(gz, Decl(callWithSpread4.ts, 13, 11)) +>RW : Symbol(RW, Decl(callWithSpread4.ts, 1, 22)) + +declare var fun: (inp: any) => AsyncGenerator +>fun : Symbol(fun, Decl(callWithSpread4.ts, 14, 11)) +>inp : Symbol(inp, Decl(callWithSpread4.ts, 14, 18)) +>AsyncGenerator : Symbol(AsyncGenerator, Decl(lib.es2018.asyncgenerator.d.ts, --, --)) + +pli( +>pli : Symbol(pli, Decl(callWithSpread4.ts, 3, 13)) + + reads, +>reads : Symbol(reads, Decl(callWithSpread4.ts, 10, 11)) + + ...gun, +>gun : Symbol(gun, Decl(callWithSpread4.ts, 12, 11)) + + tr, +>tr : Symbol(tr, Decl(callWithSpread4.ts, 11, 11)) + + fun, +>fun : Symbol(fun, Decl(callWithSpread4.ts, 14, 11)) + + ...gz, +>gz : Symbol(gz, Decl(callWithSpread4.ts, 13, 11)) + + writes +>writes : Symbol(writes, Decl(callWithSpread4.ts, 9, 11)) + +); + +declare function test(x: any, y: () => string): string | undefined; +>test : Symbol(test, Decl(callWithSpread4.ts, 22, 2)) +>x : Symbol(x, Decl(callWithSpread4.ts, 24, 22)) +>y : Symbol(y, Decl(callWithSpread4.ts, 24, 29)) + +declare var anys: any[] +>anys : Symbol(anys, Decl(callWithSpread4.ts, 25, 11)) + +test(...anys) +>test : Symbol(test, Decl(callWithSpread4.ts, 22, 2)) +>anys : Symbol(anys, Decl(callWithSpread4.ts, 25, 11)) + +pli(...[reads, writes, writes] as const) +>pli : Symbol(pli, Decl(callWithSpread4.ts, 3, 13)) +>reads : Symbol(reads, Decl(callWithSpread4.ts, 10, 11)) +>writes : Symbol(writes, Decl(callWithSpread4.ts, 9, 11)) +>writes : Symbol(writes, Decl(callWithSpread4.ts, 9, 11)) + diff --git a/tests/baselines/reference/callWithSpread4.types b/tests/baselines/reference/callWithSpread4.types new file mode 100644 index 0000000000000..5caef4eb70173 --- /dev/null +++ b/tests/baselines/reference/callWithSpread4.types @@ -0,0 +1,102 @@ +=== tests/cases/conformance/expressions/functionCalls/callWithSpread4.ts === +type R = { a: number } +>R : R +>a : number + +type W = { b: number } +>W : W +>b : number + +type RW = { a: number, b: number } +>RW : RW +>a : number +>b : number + +declare const pli: { +>pli : { (s1: R, s2: RW, s3: RW, s4: RW, s5: W): Promise; (streams: ReadonlyArray): Promise; (s1: R, s2: RW | W, ...streams: Array): Promise; } + + (s1: R, s2: RW, s3: RW, s4: RW, s5: W): Promise; +>s1 : R +>s2 : RW +>s3 : RW +>s4 : RW +>s5 : W + + (streams: ReadonlyArray): Promise; +>streams : readonly (R | W | RW)[] + + (s1: R, s2: RW | W, ...streams: Array): Promise; +>s1 : R +>s2 : W | RW +>streams : (W | RW)[] +} + +declare var writes: W +>writes : W + +declare var reads: R +>reads : R + +declare var tr: W +>tr : W + +declare var gun: RW[] +>gun : RW[] + +declare var gz: RW[] +>gz : RW[] + +declare var fun: (inp: any) => AsyncGenerator +>fun : (inp: any) => AsyncGenerator +>inp : any + +pli( +>pli( reads, ...gun, tr, fun, ...gz, writes) : Promise +>pli : { (s1: R, s2: RW, s3: RW, s4: RW, s5: W): Promise; (streams: readonly (R | W | RW)[]): Promise; (s1: R, s2: W | RW, ...streams: (W | RW)[]): Promise; } + + reads, +>reads : R + + ...gun, +>...gun : RW +>gun : RW[] + + tr, +>tr : W + + fun, +>fun : (inp: any) => AsyncGenerator + + ...gz, +>...gz : RW +>gz : RW[] + + writes +>writes : W + +); + +declare function test(x: any, y: () => string): string | undefined; +>test : (x: any, y: () => string) => string | undefined +>x : any +>y : () => string + +declare var anys: any[] +>anys : any[] + +test(...anys) +>test(...anys) : string | undefined +>test : (x: any, y: () => string) => string | undefined +>...anys : any +>anys : any[] + +pli(...[reads, writes, writes] as const) +>pli(...[reads, writes, writes] as const) : Promise +>pli : { (s1: R, s2: RW, s3: RW, s4: RW, s5: W): Promise; (streams: readonly (R | W | RW)[]): Promise; (s1: R, s2: W | RW, ...streams: (W | RW)[]): Promise; } +>...[reads, writes, writes] as const : R | W +>[reads, writes, writes] as const : readonly [R, W, W] +>[reads, writes, writes] : readonly [R, W, W] +>reads : R +>writes : W +>writes : W + diff --git a/tests/baselines/reference/callWithSpread5.errors.txt b/tests/baselines/reference/callWithSpread5.errors.txt new file mode 100644 index 0000000000000..c48101b87764a --- /dev/null +++ b/tests/baselines/reference/callWithSpread5.errors.txt @@ -0,0 +1,40 @@ +tests/cases/conformance/expressions/functionCalls/callWithSpread5.ts(16,3): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. + Type 'undefined' is not assignable to type 'number'. +tests/cases/conformance/expressions/functionCalls/callWithSpread5.ts(17,3): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. + Type 'undefined' is not assignable to type 'number'. +tests/cases/conformance/expressions/functionCalls/callWithSpread5.ts(20,6): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. + Type 'undefined' is not assignable to type 'number'. + + +==== tests/cases/conformance/expressions/functionCalls/callWithSpread5.ts (3 errors) ==== + declare const n: number + declare const nnnu: [number, number, number?] + declare const nntnnnt: [number, number] | [number, number, number] + declare const ns: number[] + declare const nununu: [number?, number?, number?] + declare const nu: [number?] + declare function setHours(a: number, b?: number, c?: number, d?: number): number + declare function f(a: number, b: number, ...c: number[]): number + declare function g(a: number, b?: number, ...c: number[]): number + + setHours(...nnnu, n) + setHours(...nntnnnt, n) + + // TODO: Handle labels too + + f(...nnnu, n) // maybe add special rules for trailing undefineds in spread tuples -> rests + ~~~~~~~ +!!! error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'undefined' is not assignable to type 'number'. + f(...nntnnnt, n) + ~~~~~~~~~~ +!!! error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'undefined' is not assignable to type 'number'. + + g(n, ...ns, n) + g(n, ...nununu, n) + ~~~~~~~~~ +!!! error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'undefined' is not assignable to type 'number'. + g(n, ...nu, n) + \ No newline at end of file diff --git a/tests/baselines/reference/callWithSpread5.js b/tests/baselines/reference/callWithSpread5.js new file mode 100644 index 0000000000000..f185f69297aa2 --- /dev/null +++ b/tests/baselines/reference/callWithSpread5.js @@ -0,0 +1,39 @@ +//// [callWithSpread5.ts] +declare const n: number +declare const nnnu: [number, number, number?] +declare const nntnnnt: [number, number] | [number, number, number] +declare const ns: number[] +declare const nununu: [number?, number?, number?] +declare const nu: [number?] +declare function setHours(a: number, b?: number, c?: number, d?: number): number +declare function f(a: number, b: number, ...c: number[]): number +declare function g(a: number, b?: number, ...c: number[]): number + +setHours(...nnnu, n) +setHours(...nntnnnt, n) + +// TODO: Handle labels too + +f(...nnnu, n) // maybe add special rules for trailing undefineds in spread tuples -> rests +f(...nntnnnt, n) + +g(n, ...ns, n) +g(n, ...nununu, n) +g(n, ...nu, n) + + +//// [callWithSpread5.js] +"use strict"; +var __spreadArray = (this && this.__spreadArray) || function (to, from) { + for (var i = 0, il = from.length, j = to.length; i < il; i++, j++) + to[j] = from[i]; + return to; +}; +setHours.apply(void 0, __spreadArray(__spreadArray([], nnnu), [n])); +setHours.apply(void 0, __spreadArray(__spreadArray([], nntnnnt), [n])); +// TODO: Handle labels too +f.apply(void 0, __spreadArray(__spreadArray([], nnnu), [n])); // maybe add special rules for trailing undefineds in spread tuples -> rests +f.apply(void 0, __spreadArray(__spreadArray([], nntnnnt), [n])); +g.apply(void 0, __spreadArray(__spreadArray([n], ns), [n])); +g.apply(void 0, __spreadArray(__spreadArray([n], nununu), [n])); +g.apply(void 0, __spreadArray(__spreadArray([n], nu), [n])); diff --git a/tests/baselines/reference/callWithSpread5.symbols b/tests/baselines/reference/callWithSpread5.symbols new file mode 100644 index 0000000000000..7c523bdab91c1 --- /dev/null +++ b/tests/baselines/reference/callWithSpread5.symbols @@ -0,0 +1,78 @@ +=== tests/cases/conformance/expressions/functionCalls/callWithSpread5.ts === +declare const n: number +>n : Symbol(n, Decl(callWithSpread5.ts, 0, 13)) + +declare const nnnu: [number, number, number?] +>nnnu : Symbol(nnnu, Decl(callWithSpread5.ts, 1, 13)) + +declare const nntnnnt: [number, number] | [number, number, number] +>nntnnnt : Symbol(nntnnnt, Decl(callWithSpread5.ts, 2, 13)) + +declare const ns: number[] +>ns : Symbol(ns, Decl(callWithSpread5.ts, 3, 13)) + +declare const nununu: [number?, number?, number?] +>nununu : Symbol(nununu, Decl(callWithSpread5.ts, 4, 13)) + +declare const nu: [number?] +>nu : Symbol(nu, Decl(callWithSpread5.ts, 5, 13)) + +declare function setHours(a: number, b?: number, c?: number, d?: number): number +>setHours : Symbol(setHours, Decl(callWithSpread5.ts, 5, 27)) +>a : Symbol(a, Decl(callWithSpread5.ts, 6, 26)) +>b : Symbol(b, Decl(callWithSpread5.ts, 6, 36)) +>c : Symbol(c, Decl(callWithSpread5.ts, 6, 48)) +>d : Symbol(d, Decl(callWithSpread5.ts, 6, 60)) + +declare function f(a: number, b: number, ...c: number[]): number +>f : Symbol(f, Decl(callWithSpread5.ts, 6, 80)) +>a : Symbol(a, Decl(callWithSpread5.ts, 7, 19)) +>b : Symbol(b, Decl(callWithSpread5.ts, 7, 29)) +>c : Symbol(c, Decl(callWithSpread5.ts, 7, 40)) + +declare function g(a: number, b?: number, ...c: number[]): number +>g : Symbol(g, Decl(callWithSpread5.ts, 7, 64)) +>a : Symbol(a, Decl(callWithSpread5.ts, 8, 19)) +>b : Symbol(b, Decl(callWithSpread5.ts, 8, 29)) +>c : Symbol(c, Decl(callWithSpread5.ts, 8, 41)) + +setHours(...nnnu, n) +>setHours : Symbol(setHours, Decl(callWithSpread5.ts, 5, 27)) +>nnnu : Symbol(nnnu, Decl(callWithSpread5.ts, 1, 13)) +>n : Symbol(n, Decl(callWithSpread5.ts, 0, 13)) + +setHours(...nntnnnt, n) +>setHours : Symbol(setHours, Decl(callWithSpread5.ts, 5, 27)) +>nntnnnt : Symbol(nntnnnt, Decl(callWithSpread5.ts, 2, 13)) +>n : Symbol(n, Decl(callWithSpread5.ts, 0, 13)) + +// TODO: Handle labels too + +f(...nnnu, n) // maybe add special rules for trailing undefineds in spread tuples -> rests +>f : Symbol(f, Decl(callWithSpread5.ts, 6, 80)) +>nnnu : Symbol(nnnu, Decl(callWithSpread5.ts, 1, 13)) +>n : Symbol(n, Decl(callWithSpread5.ts, 0, 13)) + +f(...nntnnnt, n) +>f : Symbol(f, Decl(callWithSpread5.ts, 6, 80)) +>nntnnnt : Symbol(nntnnnt, Decl(callWithSpread5.ts, 2, 13)) +>n : Symbol(n, Decl(callWithSpread5.ts, 0, 13)) + +g(n, ...ns, n) +>g : Symbol(g, Decl(callWithSpread5.ts, 7, 64)) +>n : Symbol(n, Decl(callWithSpread5.ts, 0, 13)) +>ns : Symbol(ns, Decl(callWithSpread5.ts, 3, 13)) +>n : Symbol(n, Decl(callWithSpread5.ts, 0, 13)) + +g(n, ...nununu, n) +>g : Symbol(g, Decl(callWithSpread5.ts, 7, 64)) +>n : Symbol(n, Decl(callWithSpread5.ts, 0, 13)) +>nununu : Symbol(nununu, Decl(callWithSpread5.ts, 4, 13)) +>n : Symbol(n, Decl(callWithSpread5.ts, 0, 13)) + +g(n, ...nu, n) +>g : Symbol(g, Decl(callWithSpread5.ts, 7, 64)) +>n : Symbol(n, Decl(callWithSpread5.ts, 0, 13)) +>nu : Symbol(nu, Decl(callWithSpread5.ts, 5, 13)) +>n : Symbol(n, Decl(callWithSpread5.ts, 0, 13)) + diff --git a/tests/baselines/reference/callWithSpread5.types b/tests/baselines/reference/callWithSpread5.types new file mode 100644 index 0000000000000..d36ab37dfd361 --- /dev/null +++ b/tests/baselines/reference/callWithSpread5.types @@ -0,0 +1,92 @@ +=== tests/cases/conformance/expressions/functionCalls/callWithSpread5.ts === +declare const n: number +>n : number + +declare const nnnu: [number, number, number?] +>nnnu : [number, number, (number | undefined)?] + +declare const nntnnnt: [number, number] | [number, number, number] +>nntnnnt : [number, number] | [number, number, number] + +declare const ns: number[] +>ns : number[] + +declare const nununu: [number?, number?, number?] +>nununu : [(number | undefined)?, (number | undefined)?, (number | undefined)?] + +declare const nu: [number?] +>nu : [(number | undefined)?] + +declare function setHours(a: number, b?: number, c?: number, d?: number): number +>setHours : (a: number, b?: number | undefined, c?: number | undefined, d?: number | undefined) => number +>a : number +>b : number | undefined +>c : number | undefined +>d : number | undefined + +declare function f(a: number, b: number, ...c: number[]): number +>f : (a: number, b: number, ...c: number[]) => number +>a : number +>b : number +>c : number[] + +declare function g(a: number, b?: number, ...c: number[]): number +>g : (a: number, b?: number | undefined, ...c: number[]) => number +>a : number +>b : number | undefined +>c : number[] + +setHours(...nnnu, n) +>setHours(...nnnu, n) : number +>setHours : (a: number, b?: number | undefined, c?: number | undefined, d?: number | undefined) => number +>...nnnu : number | undefined +>nnnu : [number, number, (number | undefined)?] +>n : number + +setHours(...nntnnnt, n) +>setHours(...nntnnnt, n) : number +>setHours : (a: number, b?: number | undefined, c?: number | undefined, d?: number | undefined) => number +>...nntnnnt : number +>nntnnnt : [number, number] | [number, number, number] +>n : number + +// TODO: Handle labels too + +f(...nnnu, n) // maybe add special rules for trailing undefineds in spread tuples -> rests +>f(...nnnu, n) : number +>f : (a: number, b: number, ...c: number[]) => number +>...nnnu : number | undefined +>nnnu : [number, number, (number | undefined)?] +>n : number + +f(...nntnnnt, n) +>f(...nntnnnt, n) : number +>f : (a: number, b: number, ...c: number[]) => number +>...nntnnnt : number +>nntnnnt : [number, number] | [number, number, number] +>n : number + +g(n, ...ns, n) +>g(n, ...ns, n) : number +>g : (a: number, b?: number | undefined, ...c: number[]) => number +>n : number +>...ns : number +>ns : number[] +>n : number + +g(n, ...nununu, n) +>g(n, ...nununu, n) : number +>g : (a: number, b?: number | undefined, ...c: number[]) => number +>n : number +>...nununu : number | undefined +>nununu : [(number | undefined)?, (number | undefined)?, (number | undefined)?] +>n : number + +g(n, ...nu, n) +>g(n, ...nu, n) : number +>g : (a: number, b?: number | undefined, ...c: number[]) => number +>n : number +>...nu : number | undefined +>nu : [(number | undefined)?] +>n : number + diff --git a/tests/baselines/reference/functionParameterArityMismatch.errors.txt b/tests/baselines/reference/functionParameterArityMismatch.errors.txt index 1182ecb58ab15..ab5a3f2900a2d 100644 --- a/tests/baselines/reference/functionParameterArityMismatch.errors.txt +++ b/tests/baselines/reference/functionParameterArityMismatch.errors.txt @@ -5,7 +5,7 @@ tests/cases/compiler/functionParameterArityMismatch.ts(11,1): error TS2575: No o tests/cases/compiler/functionParameterArityMismatch.ts(12,1): error TS2575: No overload expects 3 arguments, but overloads do exist that expect either 2 or 4 arguments. tests/cases/compiler/functionParameterArityMismatch.ts(13,1): error TS2575: No overload expects 5 arguments, but overloads do exist that expect either 4 or 6 arguments. tests/cases/compiler/functionParameterArityMismatch.ts(14,22): error TS2554: Expected 0-6 arguments, but got 7. -tests/cases/compiler/functionParameterArityMismatch.ts(15,12): error TS2556: Expected 0-6 arguments, but got 5 or more. +tests/cases/compiler/functionParameterArityMismatch.ts(15,4): error TS2556: A spread must either have a tuple type or be passed to a rest parameter. ==== tests/cases/compiler/functionParameterArityMismatch.ts (8 errors) ==== @@ -39,6 +39,6 @@ tests/cases/compiler/functionParameterArityMismatch.ts(15,12): error TS2556: Exp ~ !!! error TS2554: Expected 0-6 arguments, but got 7. f2(...[1], 2, 3, 4, 5, 6); - ~~~~~~~~~~~~~ -!!! error TS2556: Expected 0-6 arguments, but got 5 or more. + ~~~~~~ +!!! error TS2556: A spread must either have a tuple type or be passed to a rest parameter. \ No newline at end of file diff --git a/tests/baselines/reference/genericRestParameters2.types b/tests/baselines/reference/genericRestParameters2.types index ed4555c93694f..d4cbb42ca693e 100644 --- a/tests/baselines/reference/genericRestParameters2.types +++ b/tests/baselines/reference/genericRestParameters2.types @@ -400,7 +400,7 @@ f20(42, ...t2); >t2 : [string, ...boolean[]] f20(42, "hello", ...t3); ->f20(42, "hello", ...t3) : [number, string, ...boolean[]] +>f20(42, "hello", ...t3) : [number, string, boolean] >f20 : (...args: T) => T >42 : 42 >"hello" : "hello" diff --git a/tests/baselines/reference/genericRestParameters3.errors.txt b/tests/baselines/reference/genericRestParameters3.errors.txt index 0f2612f6b80d3..f6ec0721a9ed5 100644 --- a/tests/baselines/reference/genericRestParameters3.errors.txt +++ b/tests/baselines/reference/genericRestParameters3.errors.txt @@ -1,3 +1,13 @@ +tests/cases/conformance/types/rest/genericRestParameters3.ts(13,11): error TS2345: Argument of type '[string | number, boolean | undefined]' is not assignable to parameter of type '[string] | [number, boolean]'. + Type '[string | number, boolean | undefined]' is not assignable to type '[number, boolean]'. + Type 'string | number' is not assignable to type 'number'. + Type 'string' is not assignable to type 'number'. +tests/cases/conformance/types/rest/genericRestParameters3.ts(14,11): error TS2345: Argument of type '[string | number, boolean | undefined]' is not assignable to parameter of type '[string] | [number, boolean]'. + Type '[string | number, boolean | undefined]' is not assignable to type '[number, boolean]'. +tests/cases/conformance/types/rest/genericRestParameters3.ts(15,11): error TS2345: Argument of type '[string | number, boolean | undefined]' is not assignable to parameter of type '[string] | [number, boolean]'. + Type '[string | number, boolean | undefined]' is not assignable to type '[number, boolean]'. +tests/cases/conformance/types/rest/genericRestParameters3.ts(16,11): error TS2345: Argument of type '[string | number, boolean | undefined]' is not assignable to parameter of type '[string] | [number, boolean]'. + Type '[string | number, boolean | undefined]' is not assignable to type '[number, boolean]'. tests/cases/conformance/types/rest/genericRestParameters3.ts(17,11): error TS2345: Argument of type '[10]' is not assignable to parameter of type '[string] | [number, boolean]'. Type '[10]' is not assignable to type '[string]'. Type 'number' is not assignable to type 'string'. @@ -36,7 +46,7 @@ tests/cases/conformance/types/rest/genericRestParameters3.ts(59,5): error TS2345 Source has 1 element(s) but target requires 2. -==== tests/cases/conformance/types/rest/genericRestParameters3.ts (15 errors) ==== +==== tests/cases/conformance/types/rest/genericRestParameters3.ts (19 errors) ==== declare let f1: (x: string, ...args: [string] | [number, boolean]) => void; declare let f2: (x: string, y: string) => void; declare let f3: (x: string, y: number, z: boolean) => void; @@ -50,9 +60,23 @@ tests/cases/conformance/types/rest/genericRestParameters3.ts(59,5): error TS2345 f1("foo", "abc"); f1("foo", 10, true); f1("foo", ...t1); + ~~~~~ +!!! error TS2345: Argument of type '[string | number, boolean | undefined]' is not assignable to parameter of type '[string] | [number, boolean]'. +!!! error TS2345: Type '[string | number, boolean | undefined]' is not assignable to type '[number, boolean]'. +!!! error TS2345: Type 'string | number' is not assignable to type 'number'. +!!! error TS2345: Type 'string' is not assignable to type 'number'. f1("foo", ...t2); + ~~~~~ +!!! error TS2345: Argument of type '[string | number, boolean | undefined]' is not assignable to parameter of type '[string] | [number, boolean]'. +!!! error TS2345: Type '[string | number, boolean | undefined]' is not assignable to type '[number, boolean]'. f1("foo", ...t3); + ~~~~~ +!!! error TS2345: Argument of type '[string | number, boolean | undefined]' is not assignable to parameter of type '[string] | [number, boolean]'. +!!! error TS2345: Type '[string | number, boolean | undefined]' is not assignable to type '[number, boolean]'. f1("foo", ...t4); + ~~~~~ +!!! error TS2345: Argument of type '[string | number, boolean | undefined]' is not assignable to parameter of type '[string] | [number, boolean]'. +!!! error TS2345: Type '[string | number, boolean | undefined]' is not assignable to type '[number, boolean]'. f1("foo", 10); // Error ~~ !!! error TS2345: Argument of type '[10]' is not assignable to parameter of type '[string] | [number, boolean]'. diff --git a/tests/baselines/reference/iteratorSpreadInCall.errors.txt b/tests/baselines/reference/iteratorSpreadInCall.errors.txt index ca985c71f98e1..a412ab78724d1 100644 --- a/tests/baselines/reference/iteratorSpreadInCall.errors.txt +++ b/tests/baselines/reference/iteratorSpreadInCall.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/spread/iteratorSpreadInCall.ts(15,5): error TS2556: Expected 1 arguments, but got 0 or more. +tests/cases/conformance/es6/spread/iteratorSpreadInCall.ts(15,5): error TS2556: A spread must either have a tuple type or be passed to a rest parameter. ==== tests/cases/conformance/es6/spread/iteratorSpreadInCall.ts (1 errors) ==== @@ -18,5 +18,4 @@ tests/cases/conformance/es6/spread/iteratorSpreadInCall.ts(15,5): error TS2556: foo(...new SymbolIterator); ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2556: Expected 1 arguments, but got 0 or more. -!!! related TS6210 tests/cases/conformance/es6/spread/iteratorSpreadInCall.ts:1:14: An argument for 's' was not provided. \ No newline at end of file +!!! error TS2556: A spread must either have a tuple type or be passed to a rest parameter. \ No newline at end of file diff --git a/tests/baselines/reference/iteratorSpreadInCall10.errors.txt b/tests/baselines/reference/iteratorSpreadInCall10.errors.txt index ddbb574e076eb..896e81207ba0d 100644 --- a/tests/baselines/reference/iteratorSpreadInCall10.errors.txt +++ b/tests/baselines/reference/iteratorSpreadInCall10.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/spread/iteratorSpreadInCall10.ts(15,5): error TS2556: Expected 1 arguments, but got 0 or more. +tests/cases/conformance/es6/spread/iteratorSpreadInCall10.ts(15,5): error TS2556: A spread must either have a tuple type or be passed to a rest parameter. ==== tests/cases/conformance/es6/spread/iteratorSpreadInCall10.ts (1 errors) ==== @@ -18,5 +18,4 @@ tests/cases/conformance/es6/spread/iteratorSpreadInCall10.ts(15,5): error TS2556 foo(...new SymbolIterator); ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2556: Expected 1 arguments, but got 0 or more. -!!! related TS6210 tests/cases/conformance/es6/spread/iteratorSpreadInCall10.ts:1:17: An argument for 's' was not provided. \ No newline at end of file +!!! error TS2556: A spread must either have a tuple type or be passed to a rest parameter. \ No newline at end of file diff --git a/tests/baselines/reference/iteratorSpreadInCall2.errors.txt b/tests/baselines/reference/iteratorSpreadInCall2.errors.txt index 9074b531f6357..d694f4457e95c 100644 --- a/tests/baselines/reference/iteratorSpreadInCall2.errors.txt +++ b/tests/baselines/reference/iteratorSpreadInCall2.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/spread/iteratorSpreadInCall2.ts(15,5): error TS2556: Expected 1 arguments, but got 0 or more. +tests/cases/conformance/es6/spread/iteratorSpreadInCall2.ts(15,5): error TS2556: A spread must either have a tuple type or be passed to a rest parameter. ==== tests/cases/conformance/es6/spread/iteratorSpreadInCall2.ts (1 errors) ==== @@ -18,5 +18,4 @@ tests/cases/conformance/es6/spread/iteratorSpreadInCall2.ts(15,5): error TS2556: foo(...new SymbolIterator); ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2556: Expected 1 arguments, but got 0 or more. -!!! related TS6210 tests/cases/conformance/es6/spread/iteratorSpreadInCall2.ts:1:14: An argument for 's' was not provided. \ No newline at end of file +!!! error TS2556: A spread must either have a tuple type or be passed to a rest parameter. \ No newline at end of file diff --git a/tests/baselines/reference/iteratorSpreadInCall4.errors.txt b/tests/baselines/reference/iteratorSpreadInCall4.errors.txt index b68f7e2182683..0ae06ed2d8a79 100644 --- a/tests/baselines/reference/iteratorSpreadInCall4.errors.txt +++ b/tests/baselines/reference/iteratorSpreadInCall4.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/spread/iteratorSpreadInCall4.ts(15,5): error TS2557: Expected at least 1 arguments, but got 0 or more. +tests/cases/conformance/es6/spread/iteratorSpreadInCall4.ts(15,5): error TS2556: A spread must either have a tuple type or be passed to a rest parameter. ==== tests/cases/conformance/es6/spread/iteratorSpreadInCall4.ts (1 errors) ==== @@ -18,5 +18,4 @@ tests/cases/conformance/es6/spread/iteratorSpreadInCall4.ts(15,5): error TS2557: foo(...new SymbolIterator); ~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2557: Expected at least 1 arguments, but got 0 or more. -!!! related TS6210 tests/cases/conformance/es6/spread/iteratorSpreadInCall4.ts:1:14: An argument for 's1' was not provided. \ No newline at end of file +!!! error TS2556: A spread must either have a tuple type or be passed to a rest parameter. \ No newline at end of file diff --git a/tests/baselines/reference/noImplicitAnyLoopCrash.errors.txt b/tests/baselines/reference/noImplicitAnyLoopCrash.errors.txt index 7526354a4c5e4..b8fd242de323a 100644 --- a/tests/baselines/reference/noImplicitAnyLoopCrash.errors.txt +++ b/tests/baselines/reference/noImplicitAnyLoopCrash.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/noImplicitAnyLoopCrash.ts(4,16): error TS2556: Expected 0 arguments, but got 1 or more. +tests/cases/compiler/noImplicitAnyLoopCrash.ts(4,16): error TS2556: A spread must either have a tuple type or be passed to a rest parameter. tests/cases/compiler/noImplicitAnyLoopCrash.ts(4,19): error TS2461: Type 'number' is not an array type. @@ -8,7 +8,7 @@ tests/cases/compiler/noImplicitAnyLoopCrash.ts(4,19): error TS2461: Type 'number while (1) { bar = ~foo(...bar); ~~~~~~ -!!! error TS2556: Expected 0 arguments, but got 1 or more. +!!! error TS2556: A spread must either have a tuple type or be passed to a rest parameter. ~~~ !!! error TS2461: Type 'number' is not an array type. } diff --git a/tests/baselines/reference/readonlyRestParameters.errors.txt b/tests/baselines/reference/readonlyRestParameters.errors.txt index e2f486248d7a3..6ac1d78a8c838 100644 --- a/tests/baselines/reference/readonlyRestParameters.errors.txt +++ b/tests/baselines/reference/readonlyRestParameters.errors.txt @@ -1,4 +1,4 @@ -tests/cases/conformance/es6/restParameters/readonlyRestParameters.ts(8,8): error TS2556: Expected 2 arguments, but got 0 or more. +tests/cases/conformance/es6/restParameters/readonlyRestParameters.ts(8,8): error TS2556: A spread must either have a tuple type or be passed to a rest parameter. tests/cases/conformance/es6/restParameters/readonlyRestParameters.ts(20,15): error TS2554: Expected 2 arguments, but got 3. tests/cases/conformance/es6/restParameters/readonlyRestParameters.ts(25,5): error TS2542: Index signature in type 'readonly string[]' only permits reading. @@ -13,8 +13,7 @@ tests/cases/conformance/es6/restParameters/readonlyRestParameters.ts(25,5): erro function f1(...args: readonly string[]) { f0(...args); // Error ~~~~~~~ -!!! error TS2556: Expected 2 arguments, but got 0 or more. -!!! related TS6210 tests/cases/conformance/es6/restParameters/readonlyRestParameters.ts:1:13: An argument for 'a' was not provided. +!!! error TS2556: A spread must either have a tuple type or be passed to a rest parameter. f1('abc', 'def'); f1('abc', ...args); f1(...args); diff --git a/tests/baselines/reference/variadicTuples1.errors.txt b/tests/baselines/reference/variadicTuples1.errors.txt index 956bd6a922be2..27d895ab0e494 100644 --- a/tests/baselines/reference/variadicTuples1.errors.txt +++ b/tests/baselines/reference/variadicTuples1.errors.txt @@ -1,3 +1,5 @@ +tests/cases/conformance/types/tuple/variadicTuples1.ts(51,24): error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. + Type 'undefined' is not assignable to type 'number'. tests/cases/conformance/types/tuple/variadicTuples1.ts(52,5): error TS2555: Expected at least 3 arguments, but got 2. tests/cases/conformance/types/tuple/variadicTuples1.ts(53,17): error TS2345: Argument of type 'number' is not assignable to parameter of type 'boolean'. tests/cases/conformance/types/tuple/variadicTuples1.ts(62,5): error TS2345: Argument of type '[]' is not assignable to parameter of type '[...unknown[], number]'. @@ -40,7 +42,7 @@ tests/cases/conformance/types/tuple/variadicTuples1.ts(397,7): error TS2322: Typ Type 'boolean' is not assignable to type 'number'. -==== tests/cases/conformance/types/tuple/variadicTuples1.ts (20 errors) ==== +==== tests/cases/conformance/types/tuple/variadicTuples1.ts (21 errors) ==== // Variadics in tuple types type TV0 = [string, ...T]; @@ -92,6 +94,9 @@ tests/cases/conformance/types/tuple/variadicTuples1.ts(397,7): error TS2322: Typ foo1(...t1, true, 42, 43, 44); foo1(...t1, ...t2, 42, 43, 44); foo1(...t1, ...t2, ...a1); + ~~~~~ +!!! error TS2345: Argument of type 'number | undefined' is not assignable to parameter of type 'number'. +!!! error TS2345: Type 'undefined' is not assignable to type 'number'. foo1(...t1); // Error ~~~~~~~~~~~ !!! error TS2555: Expected at least 3 arguments, but got 2. diff --git a/tests/baselines/reference/variadicTuples2.types b/tests/baselines/reference/variadicTuples2.types index b60c45bc727f6..f52b19ec13f55 100644 --- a/tests/baselines/reference/variadicTuples2.types +++ b/tests/baselines/reference/variadicTuples2.types @@ -394,26 +394,26 @@ pipe(1, ...sa, 2, (...x) => { >...sa : string >sa : string[] >2 : 2 ->(...x) => { x; // [number, ...string[], number] let qq = x[x.length - 1]; let ww = x[0]} : (...x: [number, ...string[], number]) => void ->x : [number, ...string[], number] +>(...x) => { x; // [number, ...string[], number] let qq = x[x.length - 1]; let ww = x[0]} : (x_0: number, x_1: string, x_2: number) => void +>x : [number, string, number] x; // [number, ...string[], number] ->x : [number, ...string[], number] +>x : [number, string, number] let qq = x[x.length - 1]; >qq : string | number >x[x.length - 1] : string | number ->x : [number, ...string[], number] +>x : [number, string, number] >x.length - 1 : number ->x.length : number ->x : [number, ...string[], number] ->length : number +>x.length : 3 +>x : [number, string, number] +>length : 3 >1 : 1 let ww = x[0] >ww : number >x[0] : number ->x : [number, ...string[], number] +>x : [number, string, number] >0 : 0 }); diff --git a/tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts b/tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts index 88f9af46df5a4..9622ddaa08efd 100644 --- a/tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts +++ b/tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts @@ -21,7 +21,7 @@ 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, ...s_); // FIXME: should be a type error fs2n_(...s2_); // error on ...s2_ // ok @@ -31,5 +31,5 @@ fs2_(...s2_, ...s2_); fs2_(...s_, ...s2_); fs2n_(...s2n_); fs2n_(...s2); -// fs2n_(...s2, ...n_); // FIXME: should compile +fs2n_(...s2, ...n_); // FIXME: should compile fs5(...s2, "foo", ...s2); diff --git a/tests/cases/conformance/expressions/functionCalls/callWithSpread4.ts b/tests/cases/conformance/expressions/functionCalls/callWithSpread4.ts new file mode 100644 index 0000000000000..8b3494520dd6e --- /dev/null +++ b/tests/cases/conformance/expressions/functionCalls/callWithSpread4.ts @@ -0,0 +1,31 @@ +// @strict: true +// @target: esnext +type R = { a: number } +type W = { b: number } +type RW = { a: number, b: number } +declare const pli: { + (s1: R, s2: RW, s3: RW, s4: RW, s5: W): Promise; + (streams: ReadonlyArray): Promise; + (s1: R, s2: RW | W, ...streams: Array): Promise; +} + +declare var writes: W +declare var reads: R +declare var tr: W +declare var gun: RW[] +declare var gz: RW[] +declare var fun: (inp: any) => AsyncGenerator +pli( + reads, + ...gun, + tr, + fun, + ...gz, + writes +); + +declare function test(x: any, y: () => string): string | undefined; +declare var anys: any[] +test(...anys) + +pli(...[reads, writes, writes] as const) diff --git a/tests/cases/conformance/expressions/functionCalls/callWithSpread5.ts b/tests/cases/conformance/expressions/functionCalls/callWithSpread5.ts new file mode 100644 index 0000000000000..c7c70ffc9ce41 --- /dev/null +++ b/tests/cases/conformance/expressions/functionCalls/callWithSpread5.ts @@ -0,0 +1,22 @@ +// @strict: true +declare const n: number +declare const nnnu: [number, number, number?] +declare const nntnnnt: [number, number] | [number, number, number] +declare const ns: number[] +declare const nununu: [number?, number?, number?] +declare const nu: [number?] +declare function setHours(a: number, b?: number, c?: number, d?: number): number +declare function f(a: number, b: number, ...c: number[]): number +declare function g(a: number, b?: number, ...c: number[]): number + +setHours(...nnnu, n) +setHours(...nntnnnt, n) + +// TODO: Handle labels too + +f(...nnnu, n) // maybe add special rules for trailing undefineds in spread tuples -> rests +f(...nntnnnt, n) + +g(n, ...ns, n) +g(n, ...nununu, n) +g(n, ...nu, n)