From 26416c32f324395207659517a24a96de6a5a828c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 15 May 2017 10:17:36 -0700 Subject: [PATCH 1/5] Allow spreading arrays after required parameters This allows: 1. Spreading arrays into all-optional parameters whose types match. 2. Spreading arrays into parameter lists that are too short and whose body presumably uses `arguments`. --- src/compiler/checker.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dde60c19f4e..6c68df7c0c1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9598,6 +9598,10 @@ namespace ts { return signature.hasRestParameter && parameterIndex >= signature.parameters.length - 1; } + function areAllParametersOptionalAfter(signature: Signature, parameterIndex: number) { + return parameterIndex >= signature.minArgumentCount; + } + function isSupertypeOfEach(candidate: Type, types: Type[]): boolean { for (const t of types) { if (candidate !== t && !isTypeSubtypeOf(t, candidate)) return false; @@ -14649,7 +14653,7 @@ namespace ts { // If spread arguments are present, check that they correspond to a rest parameter. If so, no // further checking is necessary. if (spreadArgIndex >= 0) { - return isRestParameterIndex(signature, spreadArgIndex); + return isRestParameterIndex(signature, spreadArgIndex) || areAllParametersOptionalAfter(signature, spreadArgIndex); } // Too many arguments implies incorrect arity. From 9ba0668afafdbfd6d2a0212f4a2861bdb7a2124a Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 15 May 2017 10:20:28 -0700 Subject: [PATCH 2/5] Test:spread array after required params --- .../reference/callWithSpread2.errors.txt | 94 +++++++++++++++++++ tests/baselines/reference/callWithSpread2.js | 80 ++++++++++++++++ .../functionCalls/callWithSpread2.ts | 48 ++++++++++ 3 files changed, 222 insertions(+) create mode 100644 tests/baselines/reference/callWithSpread2.errors.txt create mode 100644 tests/baselines/reference/callWithSpread2.js create mode 100644 tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts diff --git a/tests/baselines/reference/callWithSpread2.errors.txt b/tests/baselines/reference/callWithSpread2.errors.txt new file mode 100644 index 00000000000..f12846ab1cd --- /dev/null +++ b/tests/baselines/reference/callWithSpread2.errors.txt @@ -0,0 +1,94 @@ +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(40,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(41,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(42,13): 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(43,13): 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(44,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(45,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(46,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(46,11): error TS2461: Type '(a?: number, b?: number) => void' is not an array type. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(47,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(48,1): error TS2346: Supplied parameters do not match any signature of call target. + + +==== tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts (10 errors) ==== + // Desired semantics: take type of array that is spread, + // allow it to be applied to a + // *trailing* set of optional parameters whose types match. + // Length is *not* checked, the parameters it's applied to just have to be optional. + + // that means that tuples are non-starters because their array element type + // is a union like string | number. + + // with exceptions for JS functions that use arguments, or maybe all JS functions + + declare function all(a?: number, b?: number): void; + declare function weird(a?: number | string, b?: number | string): void; + declare function prefix(s: string, a?: number, b?: number): void; + declare function rest(s: string, a?: number, b?: number, ...rest: number[]): void; + declare function normal(s: string): void; + declare function thunk(): string; + + declare var ns: number[]; + declare var mixed: (number | string)[]; + declare var tuple: [number, string]; + + // good + all(...ns) + weird(...ns) + weird(...mixed) + weird(...tuple) + prefix("a", ...ns) + rest("d", ...ns) + + + // this covers the arguments case + normal("g", ...ns) + normal("h", ...mixed) + normal("i", ...tuple) + thunk(...ns) + thunk(...mixed) + thunk(...tuple) + + // bad + all(...mixed) + ~~~~~~~~ +!!! 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'. + all(...tuple) + ~~~~~~~~ +!!! 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'. + prefix("b", ...mixed) + ~~~~~~~~ +!!! 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'. + prefix("c", ...tuple) + ~~~~~~~~ +!!! 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'. + rest("e", ...mixed) + ~~~~~~~~ +!!! 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'. + rest("f", ...tuple) + ~~~~~~~~ +!!! 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'. + prefix(...all) // required parameters are required + ~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + ~~~ +!!! error TS2461: Type '(a?: number, b?: number) => void' is not an array type. + prefix(...mixed) + ~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + prefix(...tuple) + ~~~~~~~~~~~~~~~~ +!!! error TS2346: Supplied parameters do not match any signature of call target. + \ No newline at end of file diff --git a/tests/baselines/reference/callWithSpread2.js b/tests/baselines/reference/callWithSpread2.js new file mode 100644 index 00000000000..25ccc582093 --- /dev/null +++ b/tests/baselines/reference/callWithSpread2.js @@ -0,0 +1,80 @@ +//// [callWithSpread2.ts] +// Desired semantics: take type of array that is spread, +// allow it to be applied to a +// *trailing* set of optional parameters whose types match. +// Length is *not* checked, the parameters it's applied to just have to be optional. + +// that means that tuples are non-starters because their array element type +// is a union like string | number. + +// with exceptions for JS functions that use arguments, or maybe all JS functions + +declare function all(a?: number, b?: number): void; +declare function weird(a?: number | string, b?: number | string): void; +declare function prefix(s: string, a?: number, b?: number): void; +declare function rest(s: string, a?: number, b?: number, ...rest: number[]): void; +declare function normal(s: string): void; +declare function thunk(): string; + +declare var ns: number[]; +declare var mixed: (number | string)[]; +declare var tuple: [number, string]; + +// good +all(...ns) +weird(...ns) +weird(...mixed) +weird(...tuple) +prefix("a", ...ns) +rest("d", ...ns) + + +// this covers the arguments case +normal("g", ...ns) +normal("h", ...mixed) +normal("i", ...tuple) +thunk(...ns) +thunk(...mixed) +thunk(...tuple) + +// bad +all(...mixed) +all(...tuple) +prefix("b", ...mixed) +prefix("c", ...tuple) +rest("e", ...mixed) +rest("f", ...tuple) +prefix(...all) // required parameters are required +prefix(...mixed) +prefix(...tuple) + + +//// [callWithSpread2.js] +// Desired semantics: take type of array that is spread, +// allow it to be applied to a +// *trailing* set of optional parameters whose types match. +// Length is *not* checked, the parameters it's applied to just have to be optional. +// good +all.apply(void 0, ns); +weird.apply(void 0, ns); +weird.apply(void 0, mixed); +weird.apply(void 0, tuple); +prefix.apply(void 0, ["a"].concat(ns)); +rest.apply(void 0, ["d"].concat(ns)); +// this covers the arguments case +normal.apply(void 0, ["g"].concat(ns)); +normal.apply(void 0, ["h"].concat(mixed)); +normal.apply(void 0, ["i"].concat(tuple)); +thunk.apply(void 0, ns); +thunk.apply(void 0, mixed); +thunk.apply(void 0, tuple); +// bad +all.apply(void 0, mixed); +all.apply(void 0, tuple); +prefix.apply(void 0, ["b"].concat(mixed)); +prefix.apply(void 0, ["c"].concat(tuple)); +rest.apply(void 0, ["e"].concat(mixed)); +rest.apply(void 0, ["f"].concat(tuple)); +prefix.apply(void 0, all); // required parameters are required +prefix.apply(void 0, mixed); +prefix.apply(void 0, tuple); diff --git a/tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts b/tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts new file mode 100644 index 00000000000..72ff97f7c90 --- /dev/null +++ b/tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts @@ -0,0 +1,48 @@ +// Desired semantics: take type of array that is spread, +// allow it to be applied to a +// *trailing* set of optional parameters whose types match. +// Length is *not* checked, the parameters it's applied to just have to be optional. + +// that means that tuples are non-starters because their array element type +// is a union like string | number. + +// with exceptions for JS functions that use arguments, or maybe all JS functions + +declare function all(a?: number, b?: number): void; +declare function weird(a?: number | string, b?: number | string): void; +declare function prefix(s: string, a?: number, b?: number): void; +declare function rest(s: string, a?: number, b?: number, ...rest: number[]): void; +declare function normal(s: string): void; +declare function thunk(): string; + +declare var ns: number[]; +declare var mixed: (number | string)[]; +declare var tuple: [number, string]; + +// good +all(...ns) +weird(...ns) +weird(...mixed) +weird(...tuple) +prefix("a", ...ns) +rest("d", ...ns) + + +// this covers the arguments case +normal("g", ...ns) +normal("h", ...mixed) +normal("i", ...tuple) +thunk(...ns) +thunk(...mixed) +thunk(...tuple) + +// bad +all(...mixed) +all(...tuple) +prefix("b", ...mixed) +prefix("c", ...tuple) +rest("e", ...mixed) +rest("f", ...tuple) +prefix(...all) // required parameters are required +prefix(...mixed) +prefix(...tuple) From b61eaf70a1587ad0d171ec3141ad90fe1a34d764 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 15 May 2017 10:31:47 -0700 Subject: [PATCH 3/5] Inline function that is called once --- src/compiler/checker.ts | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 6c68df7c0c1..9e6a5f946b3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9598,10 +9598,6 @@ namespace ts { return signature.hasRestParameter && parameterIndex >= signature.parameters.length - 1; } - function areAllParametersOptionalAfter(signature: Signature, parameterIndex: number) { - return parameterIndex >= signature.minArgumentCount; - } - function isSupertypeOfEach(candidate: Type, types: Type[]): boolean { for (const t of types) { if (candidate !== t && !isTypeSubtypeOf(t, candidate)) return false; @@ -14653,7 +14649,7 @@ namespace ts { // If spread arguments are present, check that they correspond to a rest parameter. If so, no // further checking is necessary. if (spreadArgIndex >= 0) { - return isRestParameterIndex(signature, spreadArgIndex) || areAllParametersOptionalAfter(signature, spreadArgIndex); + return isRestParameterIndex(signature, spreadArgIndex) || spreadArgIndex >= signature.minArgumentCount; } // Too many arguments implies incorrect arity. From 4c80aa17b3e1f04283f821638b90f6daf679b237 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 15 May 2017 10:38:51 -0700 Subject: [PATCH 4/5] Clean up comments in tests --- .../reference/callWithSpread2.errors.txt | 30 +++++++------------ tests/baselines/reference/callWithSpread2.js | 14 --------- .../functionCalls/callWithSpread2.ts | 10 ------- 3 files changed, 10 insertions(+), 44 deletions(-) diff --git a/tests/baselines/reference/callWithSpread2.errors.txt b/tests/baselines/reference/callWithSpread2.errors.txt index f12846ab1cd..770e33c9ae9 100644 --- a/tests/baselines/reference/callWithSpread2.errors.txt +++ b/tests/baselines/reference/callWithSpread2.errors.txt @@ -1,32 +1,22 @@ -tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(40,5): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(30,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(41,5): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(31,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(42,13): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(32,13): 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(43,13): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(33,13): 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(44,11): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(34,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(45,11): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'number'. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(35,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(46,1): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(46,11): error TS2461: Type '(a?: number, b?: number) => void' is not an array type. -tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(47,1): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(48,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(36,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(36,11): error TS2461: Type '(a?: number, b?: number) => void' is not an array type. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(37,1): error TS2346: Supplied parameters do not match any signature of call target. +tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(38,1): error TS2346: Supplied parameters do not match any signature of call target. ==== tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts (10 errors) ==== - // Desired semantics: take type of array that is spread, - // allow it to be applied to a - // *trailing* set of optional parameters whose types match. - // Length is *not* checked, the parameters it's applied to just have to be optional. - - // that means that tuples are non-starters because their array element type - // is a union like string | number. - - // with exceptions for JS functions that use arguments, or maybe all JS functions - declare function all(a?: number, b?: number): void; declare function weird(a?: number | string, b?: number | string): void; declare function prefix(s: string, a?: number, b?: number): void; diff --git a/tests/baselines/reference/callWithSpread2.js b/tests/baselines/reference/callWithSpread2.js index 25ccc582093..0380c69f80f 100644 --- a/tests/baselines/reference/callWithSpread2.js +++ b/tests/baselines/reference/callWithSpread2.js @@ -1,14 +1,4 @@ //// [callWithSpread2.ts] -// Desired semantics: take type of array that is spread, -// allow it to be applied to a -// *trailing* set of optional parameters whose types match. -// Length is *not* checked, the parameters it's applied to just have to be optional. - -// that means that tuples are non-starters because their array element type -// is a union like string | number. - -// with exceptions for JS functions that use arguments, or maybe all JS functions - declare function all(a?: number, b?: number): void; declare function weird(a?: number | string, b?: number | string): void; declare function prefix(s: string, a?: number, b?: number): void; @@ -50,10 +40,6 @@ prefix(...tuple) //// [callWithSpread2.js] -// Desired semantics: take type of array that is spread, -// allow it to be applied to a -// *trailing* set of optional parameters whose types match. -// Length is *not* checked, the parameters it's applied to just have to be optional. // good all.apply(void 0, ns); weird.apply(void 0, ns); diff --git a/tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts b/tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts index 72ff97f7c90..07441dc74bf 100644 --- a/tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts +++ b/tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts @@ -1,13 +1,3 @@ -// Desired semantics: take type of array that is spread, -// allow it to be applied to a -// *trailing* set of optional parameters whose types match. -// Length is *not* checked, the parameters it's applied to just have to be optional. - -// that means that tuples are non-starters because their array element type -// is a union like string | number. - -// with exceptions for JS functions that use arguments, or maybe all JS functions - declare function all(a?: number, b?: number): void; declare function weird(a?: number | string, b?: number | string): void; declare function prefix(s: string, a?: number, b?: number): void; From cefcc668a881a52b71db6e601ba70c00f1c36332 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 15 May 2017 10:55:58 -0700 Subject: [PATCH 5/5] Correct test argument in callwithSpread2 --- tests/baselines/reference/callWithSpread2.errors.txt | 9 +++------ tests/baselines/reference/callWithSpread2.js | 4 ++-- .../expressions/functionCalls/callWithSpread2.ts | 2 +- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/tests/baselines/reference/callWithSpread2.errors.txt b/tests/baselines/reference/callWithSpread2.errors.txt index 770e33c9ae9..cfea427a2a7 100644 --- a/tests/baselines/reference/callWithSpread2.errors.txt +++ b/tests/baselines/reference/callWithSpread2.errors.txt @@ -11,12 +11,11 @@ tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(34,11): err tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(35,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(36,1): error TS2346: Supplied parameters do not match any signature of call target. -tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(36,11): error TS2461: Type '(a?: number, b?: number) => void' is not an array type. tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(37,1): error TS2346: Supplied parameters do not match any signature of call target. tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(38,1): error TS2346: Supplied parameters do not match any signature of call target. -==== tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts (10 errors) ==== +==== tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts (9 errors) ==== declare function all(a?: number, b?: number): void; declare function weird(a?: number | string, b?: number | string): void; declare function prefix(s: string, a?: number, b?: number): void; @@ -70,11 +69,9 @@ tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts(38,1): erro ~~~~~~~~ !!! 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'. - prefix(...all) // required parameters are required - ~~~~~~~~~~~~~~ + prefix(...ns) // required parameters are required + ~~~~~~~~~~~~~ !!! error TS2346: Supplied parameters do not match any signature of call target. - ~~~ -!!! error TS2461: Type '(a?: number, b?: number) => void' is not an array type. prefix(...mixed) ~~~~~~~~~~~~~~~~ !!! error TS2346: Supplied parameters do not match any signature of call target. diff --git a/tests/baselines/reference/callWithSpread2.js b/tests/baselines/reference/callWithSpread2.js index 0380c69f80f..55296d924f7 100644 --- a/tests/baselines/reference/callWithSpread2.js +++ b/tests/baselines/reference/callWithSpread2.js @@ -34,7 +34,7 @@ prefix("b", ...mixed) prefix("c", ...tuple) rest("e", ...mixed) rest("f", ...tuple) -prefix(...all) // required parameters are required +prefix(...ns) // required parameters are required prefix(...mixed) prefix(...tuple) @@ -61,6 +61,6 @@ prefix.apply(void 0, ["b"].concat(mixed)); prefix.apply(void 0, ["c"].concat(tuple)); rest.apply(void 0, ["e"].concat(mixed)); rest.apply(void 0, ["f"].concat(tuple)); -prefix.apply(void 0, all); // required parameters are required +prefix.apply(void 0, ns); // required parameters are required prefix.apply(void 0, mixed); prefix.apply(void 0, tuple); diff --git a/tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts b/tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts index 07441dc74bf..9151f52f00d 100644 --- a/tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts +++ b/tests/cases/conformance/expressions/functionCalls/callWithSpread2.ts @@ -33,6 +33,6 @@ prefix("b", ...mixed) prefix("c", ...tuple) rest("e", ...mixed) rest("f", ...tuple) -prefix(...all) // required parameters are required +prefix(...ns) // required parameters are required prefix(...mixed) prefix(...tuple)