从 javascript t typescript 函数转换展开运算符

Kai*_*r69 7 javascript typescript

我无法将这段代码从 Javascript 转换为 Typescript。

问题是转换 ...spread 运算符。

function calculateCombinations(first, next, ...rest) {

  if (rest.length) {
    next = calculateCombinations(next, ...rest);
  }


  return first.flatMap(a => next.map(b => [a, b].flat()));
}


a1 = ['A', 'B']
a2 = ['+', '-']
a3 = ['1', '2']
a4 = ['X', 'Y', 'Z']
// Show possibile combinations
calculateCombinations(a1, a2, a3, a4); // give me an array of 24 combinations
Run Code Online (Sandbox Code Playgroud)

尝试转换为 TS:

  function calculateCombinationsTS(first: any[], next: any[], ...rest: any[]) {
    if (rest.length) {
        next = calculateCombinationsTS(next, ...rest);
    }

   return first.flatMap(a => next.map(b => [a, b].flat()));
  }
Run Code Online (Sandbox Code Playgroud)

TS2556:扩展参数必须具有元组类型或传递给剩余参数。

如果我改变

 next = calculateCombinationsTS(next, ...rest);
Run Code Online (Sandbox Code Playgroud)

 next = calculateCombinationsTS(next, rest);
Run Code Online (Sandbox Code Playgroud)

该函数给了我一个错误的结果,因为其余部分作为数组的数组而不是参数列表传递

输出示例:

nCombo = (a1 * a2 * a3 * a4) = 24 possibilities
[
  [ 'A', '+', '1', 'X' ], [ 'A', '+', '1', 'Y' ],
  [ 'A', '+', '1', 'Z' ], [ 'A', '+', '2', 'X' ],
  [ 'A', '+', '2', 'Y' ], [ 'A', '+', '2', 'Z' ],
  [ 'A', '-', '1', 'X' ], [ 'A', '-', '1', 'Y' ],
  [ 'A', '-', '1', 'Z' ], [ 'A', '-', '2', 'X' ],
  [ 'A', '-', '2', 'Y' ], [ 'A', '-', '2', 'Z' ],
  [ 'B', '+', '1', 'X' ], [ 'B', '+', '1', 'Y' ],
  [ 'B', '+', '1', 'Z' ], [ 'B', '+', '2', 'X' ],
  [ 'B', '+', '2', 'Y' ], [ 'B', '+', '2', 'Z' ],
  [ 'B', '-', '1', 'X' ], [ 'B', '-', '1', 'Y' ],
  [ 'B', '-', '1', 'Z' ], [ 'B', '-', '2', 'X' ],
  [ 'B', '-', '2', 'Y' ], [ 'B', '-', '2', 'Z' ] 
]
Run Code Online (Sandbox Code Playgroud)

T.J*_*der 3

有两个问题:

\n
    \n
  1. 如果要为剩余参数传递一系列数组参数,则剩余参数必须是数组的数组,而不仅仅是数组。所以:...rest: any[][]。TypeScript 并没有抱怨这一点,因为你可以使用数组来表示any,但它更准确地反映了你正在做的事情。

    \n
  2. \n
  3. TypeScript 无法判断调用是否calculateCombinationsTS(next, ...more);会将参数传递给next函数,即使您进行了检查rest.length并且知道它会传递参数。您需要使用两个离散参数调用该函数,然后(可选)扩展一个数组。您可以通过从参数中获取第一个元素rest并显式传递它来解决此问题:

    \n
    if (rest.length) {\n    const [first, ...more] = rest;\n    next = calculateCombinationsTS(next, first, ...more);\n}\n
    Run Code Online (Sandbox Code Playgroud)\n

    理论上,这可能会增加开销。在实践中,我怀疑开销将得到充分优化,不会成为问题。

    \n

    或者,由于您知道调用是正确的(因为您知道rest其中至少有一个元素),因此您可以使用 a 来消除错误@ts-ignore,但我会尽力避免这些错误。

    \n
  4. \n
\n

解决这两个问题的完整功能:

\n
function calculateCombinationsTS(first: any[], next: any[], ...rest: any[][]) {\n// \xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92\xe2\x88\x92^^\n   if (rest.length) {\n       const [first, ...more] = rest;                        // ***\n       next = calculateCombinationsTS(next, first, ...more); // ***\n   }\n\n   return first.flatMap((a) => next.map((b) => [a, b].flat()));\n}\n
Run Code Online (Sandbox Code Playgroud)\n

可运行的 Playground 示例从您的示例中生成 72 种组合

\n