mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
fix error when use spread arguments twice
This commit is contained in:
+18
-5
@@ -25063,10 +25063,18 @@ namespace ts {
|
||||
// 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) {
|
||||
return firstSpreadArgIndex >= getMinArgumentCount(signature) && (hasEffectiveRestParameter(signature) || firstSpreadArgIndex < getParameterCount(signature));
|
||||
}
|
||||
|
||||
let totalCount = countSpreadArgumentLength(<SpreadElement>args[firstSpreadArgIndex]);
|
||||
for (let i = firstSpreadArgIndex; i < args.length; i++) {
|
||||
totalCount += isSpreadArgument(args[i]) ? countSpreadArgumentLength(<SpreadElement>args[i]) : 1;
|
||||
}
|
||||
return totalCount >= getMinArgumentCount(signature) && (hasEffectiveRestParameter(signature) || totalCount < getParameterCount(signature));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25089,6 +25097,11 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
function countSpreadArgumentLength(argment: SpreadElement): number {
|
||||
const type = flowLoopCount ? checkExpression(argment.expression) : checkExpressionCached(argment.expression);
|
||||
return isTupleType(type) ? getTypeArguments(type).length : 1;
|
||||
}
|
||||
|
||||
function hasCorrectTypeArgumentArity(signature: Signature, typeArguments: NodeArray<TypeNode> | undefined) {
|
||||
// If the user supplied type arguments, but the number of type arguments does not match
|
||||
// the declared number of type parameters, the call has an incorrect arity.
|
||||
@@ -25544,7 +25557,7 @@ namespace ts {
|
||||
const spreadArgument = <SpreadElement>args[length - 1];
|
||||
const type = flowLoopCount ? checkExpression(spreadArgument.expression) : checkExpressionCached(spreadArgument.expression);
|
||||
if (isTupleType(type)) {
|
||||
const typeArguments = getTypeArguments(<TypeReference>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);
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
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(9,14): error TS2554: Expected 2 arguments, but got 3.
|
||||
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(10,19): error TS2554: Expected 2 arguments, but got 5.
|
||||
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(11,19): error TS2556: Expected 2 arguments, but got 4 or more.
|
||||
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(12,19): error TS2556: Expected 2 arguments, but got 5 or more.
|
||||
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(13,16): error TS2556: Expected 2 arguments, but got 1 or more.
|
||||
tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(14,9): error TS2554: Expected 2 arguments, but got 3.
|
||||
|
||||
|
||||
==== 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];
|
||||
declare function takeTwoOrMore (a: string, b: string, ...c: string[]): void
|
||||
declare const t4: [string, string, ...string[]]
|
||||
declare const t5: string[]
|
||||
|
||||
// error
|
||||
takeTwo('a', ...t2); // error on ...t2
|
||||
~~~~~
|
||||
!!! error TS2554: Expected 2 arguments, but got 3.
|
||||
@@ -29,4 +33,11 @@ tests/cases/conformance/expressions/functionCalls/callWithSpread3.ts(10,9): erro
|
||||
!!! 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.
|
||||
!!! error TS2554: Expected 2 arguments, but got 3.
|
||||
|
||||
// ok
|
||||
takeTwoOrMore(...t4);
|
||||
takeTwoOrMore(...t4, ...t5);
|
||||
takeTwoOrMore(...t4, ...t4);
|
||||
takeTwoOrMore(...t5, ...t4);
|
||||
|
||||
@@ -2,13 +2,24 @@
|
||||
declare function takeTwo(a: string, b: string): void;
|
||||
declare const t2: [string, string];
|
||||
declare const t3: [string, string, string];
|
||||
declare function takeTwoOrMore (a: string, b: string, ...c: string[]): void
|
||||
declare const t4: [string, string, ...string[]]
|
||||
declare const t5: string[]
|
||||
|
||||
// error
|
||||
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
|
||||
takeTwo(...t3); // error on ...t3
|
||||
|
||||
// ok
|
||||
takeTwoOrMore(...t4);
|
||||
takeTwoOrMore(...t4, ...t5);
|
||||
takeTwoOrMore(...t4, ...t4);
|
||||
takeTwoOrMore(...t5, ...t4);
|
||||
|
||||
|
||||
//// [callWithSpread3.js]
|
||||
var __spreadArrays = (this && this.__spreadArrays) || function () {
|
||||
@@ -18,9 +29,15 @@ var __spreadArrays = (this && this.__spreadArrays) || function () {
|
||||
r[k] = a[j];
|
||||
return r;
|
||||
};
|
||||
// error
|
||||
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
|
||||
// ok
|
||||
takeTwoOrMore.apply(void 0, t4);
|
||||
takeTwoOrMore.apply(void 0, __spreadArrays(t4, t5));
|
||||
takeTwoOrMore.apply(void 0, __spreadArrays(t4, t4));
|
||||
takeTwoOrMore.apply(void 0, __spreadArrays(t5, t4));
|
||||
|
||||
@@ -10,6 +10,19 @@ declare const t2: [string, string];
|
||||
declare const t3: [string, string, string];
|
||||
>t3 : Symbol(t3, Decl(callWithSpread3.ts, 2, 13))
|
||||
|
||||
declare function takeTwoOrMore (a: string, b: string, ...c: string[]): void
|
||||
>takeTwoOrMore : Symbol(takeTwoOrMore, Decl(callWithSpread3.ts, 2, 43))
|
||||
>a : Symbol(a, Decl(callWithSpread3.ts, 3, 32))
|
||||
>b : Symbol(b, Decl(callWithSpread3.ts, 3, 42))
|
||||
>c : Symbol(c, Decl(callWithSpread3.ts, 3, 53))
|
||||
|
||||
declare const t4: [string, string, ...string[]]
|
||||
>t4 : Symbol(t4, Decl(callWithSpread3.ts, 4, 13))
|
||||
|
||||
declare const t5: string[]
|
||||
>t5 : Symbol(t5, Decl(callWithSpread3.ts, 5, 13))
|
||||
|
||||
// error
|
||||
takeTwo('a', ...t2); // error on ...t2
|
||||
>takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0))
|
||||
>t2 : Symbol(t2, Decl(callWithSpread3.ts, 1, 13))
|
||||
@@ -34,3 +47,23 @@ takeTwo(...t3); // error on ...t3
|
||||
>takeTwo : Symbol(takeTwo, Decl(callWithSpread3.ts, 0, 0))
|
||||
>t3 : Symbol(t3, Decl(callWithSpread3.ts, 2, 13))
|
||||
|
||||
// ok
|
||||
takeTwoOrMore(...t4);
|
||||
>takeTwoOrMore : Symbol(takeTwoOrMore, Decl(callWithSpread3.ts, 2, 43))
|
||||
>t4 : Symbol(t4, Decl(callWithSpread3.ts, 4, 13))
|
||||
|
||||
takeTwoOrMore(...t4, ...t5);
|
||||
>takeTwoOrMore : Symbol(takeTwoOrMore, Decl(callWithSpread3.ts, 2, 43))
|
||||
>t4 : Symbol(t4, Decl(callWithSpread3.ts, 4, 13))
|
||||
>t5 : Symbol(t5, Decl(callWithSpread3.ts, 5, 13))
|
||||
|
||||
takeTwoOrMore(...t4, ...t4);
|
||||
>takeTwoOrMore : Symbol(takeTwoOrMore, Decl(callWithSpread3.ts, 2, 43))
|
||||
>t4 : Symbol(t4, Decl(callWithSpread3.ts, 4, 13))
|
||||
>t4 : Symbol(t4, Decl(callWithSpread3.ts, 4, 13))
|
||||
|
||||
takeTwoOrMore(...t5, ...t4);
|
||||
>takeTwoOrMore : Symbol(takeTwoOrMore, Decl(callWithSpread3.ts, 2, 43))
|
||||
>t5 : Symbol(t5, Decl(callWithSpread3.ts, 5, 13))
|
||||
>t4 : Symbol(t4, Decl(callWithSpread3.ts, 4, 13))
|
||||
|
||||
|
||||
@@ -10,6 +10,19 @@ declare const t2: [string, string];
|
||||
declare const t3: [string, string, string];
|
||||
>t3 : [string, string, string]
|
||||
|
||||
declare function takeTwoOrMore (a: string, b: string, ...c: string[]): void
|
||||
>takeTwoOrMore : (a: string, b: string, ...c: string[]) => void
|
||||
>a : string
|
||||
>b : string
|
||||
>c : string[]
|
||||
|
||||
declare const t4: [string, string, ...string[]]
|
||||
>t4 : [string, string, ...string[]]
|
||||
|
||||
declare const t5: string[]
|
||||
>t5 : string[]
|
||||
|
||||
// error
|
||||
takeTwo('a', ...t2); // error on ...t2
|
||||
>takeTwo('a', ...t2) : void
|
||||
>takeTwo : (a: string, b: string) => void
|
||||
@@ -58,3 +71,34 @@ takeTwo(...t3); // error on ...t3
|
||||
>...t3 : string
|
||||
>t3 : [string, string, string]
|
||||
|
||||
// ok
|
||||
takeTwoOrMore(...t4);
|
||||
>takeTwoOrMore(...t4) : void
|
||||
>takeTwoOrMore : (a: string, b: string, ...c: string[]) => void
|
||||
>...t4 : string
|
||||
>t4 : [string, string, ...string[]]
|
||||
|
||||
takeTwoOrMore(...t4, ...t5);
|
||||
>takeTwoOrMore(...t4, ...t5) : void
|
||||
>takeTwoOrMore : (a: string, b: string, ...c: string[]) => void
|
||||
>...t4 : string
|
||||
>t4 : [string, string, ...string[]]
|
||||
>...t5 : string
|
||||
>t5 : string[]
|
||||
|
||||
takeTwoOrMore(...t4, ...t4);
|
||||
>takeTwoOrMore(...t4, ...t4) : void
|
||||
>takeTwoOrMore : (a: string, b: string, ...c: string[]) => void
|
||||
>...t4 : string
|
||||
>t4 : [string, string, ...string[]]
|
||||
>...t4 : string
|
||||
>t4 : [string, string, ...string[]]
|
||||
|
||||
takeTwoOrMore(...t5, ...t4);
|
||||
>takeTwoOrMore(...t5, ...t4) : void
|
||||
>takeTwoOrMore : (a: string, b: string, ...c: string[]) => void
|
||||
>...t5 : string
|
||||
>t5 : string[]
|
||||
>...t4 : string
|
||||
>t4 : [string, string, ...string[]]
|
||||
|
||||
|
||||
@@ -1,10 +1,20 @@
|
||||
declare function takeTwo(a: string, b: string): void;
|
||||
declare const t2: [string, string];
|
||||
declare const t3: [string, string, string];
|
||||
declare function takeTwoOrMore (a: string, b: string, ...c: string[]): void
|
||||
declare const t4: [string, string, ...string[]]
|
||||
declare const t5: string[]
|
||||
|
||||
// error
|
||||
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
|
||||
takeTwo(...t3); // error on ...t3
|
||||
|
||||
// ok
|
||||
takeTwoOrMore(...t4);
|
||||
takeTwoOrMore(...t4, ...t5);
|
||||
takeTwoOrMore(...t4, ...t4);
|
||||
takeTwoOrMore(...t5, ...t4);
|
||||
|
||||
Reference in New Issue
Block a user