将JavaScript中的扩展运算符转换为TypeScript函数。

7

我无法将那段JavaScript代码转换为TypeScript。

问题在于如何将扩展运算符...转换。

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

尝试将代码转换为 TypeScript:

  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()));
  }

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

如果我更改

 next = calculateCombinationsTS(next, ...rest);

to

 next = calculateCombinationsTS(next, rest);

函数给我一个错误的结果,是因为rest被传递为数组中的数组而不是参数列表。
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' ] 
]

是的,我已经放了一个输出示例。 - Kaiser69
1
我已经更新了问题,提供了一些避免过于复杂的组合示例 :) - Kaiser69
3个回答

3

有两个问题:

  1. If you want to pass a series of array arguments for your rest parameter, you rest parameter must be an array of arrays, not just an array. So: ...rest: any[][]. TypeScript isn't complaining about that because you can use an array for any, but it's a more accurate reflection of what you're doing.

  2. TypeScript can't tell that the call calculateCombinationsTS(next, ...more); will pass an argument for next to the function, even though you have a check on rest.length and so you know it will. You need to call the function with two discrete arguments, followed (optionally) by spreading an array. You can fix that by grabbing the first element from the rest parameter and passing it explicitly:

    if (rest.length) {
        const [first, ...more] = rest;
        next = calculateCombinationsTS(next, first, ...more);
    }
    

    In theory, that might add overhead. In practice, I suspect the overhead will be sufficiently optimized to not be an issue.

    Or, since you know the call is correct (because you know rest has at least one element in it), you could silence the error with a @ts-ignore, but I try to avoid those where I can.

修复这两个问题的完整函数:

function calculateCombinationsTS(first: any[], next: any[], ...rest: any[][]) {
// −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^
   if (rest.length) {
       const [first, ...more] = rest;                        // ***
       next = calculateCombinationsTS(next, first, ...more); // ***
   }

   return first.flatMap((a) => next.map((b) => [a, b].flat()));
}
可运行的播放示例生成您示例中的72种组合。

1

试试这个

next = calculateCombinationsTS(next, rest[0], ...rest.slice(1));

如果您使用相同的签名(首先,接下来,...spread)显式调用函数,则Typescript将更加愉快。


1
我没有给它点踩(实际上我做了相反的事情),但我怀疑这是因为缺乏有意义的解释。代码转储通常不是有用的答案,更好的方法是说出你做了什么,为什么这样做以及它如何解决问题。但是,是的,这将解决OP所问的代码问题。 - T.J. Crowder
我确认你的代码也可以运行。 - Kaiser69
谢谢您,@T.J.Crowder。我是新手,我的回答太简短了。我会注意改进的!(您自己的答案是一个很好的解释性解决方案的例子) - dorwinrin

-1
问题在于你如何调用函数,这不是 TypeScript 的问题。
`calculateCombinations` 需要 2 个必需的参数,然后是一些其他参数,但是当你递归调用它时,你只发送了一个必需的参数。
当你说 `calculateCombinations(next, ...rest)` 时,TypeScript 认为 `next: any[]` 应该是一个展开运算符。

rest.length 的测试确保递归调用是正确的。(只是 TypeScript 不知道而已。) - T.J. Crowder
我不知道为什么会出现这个错误,但有一件事是确定的:当至少发送3个参数时,TypeScript问题就会消失。 - ThomasG2201
1
使用3个参数,TypeScript不会显示错误,但函数的结果是错误的。 - Kaiser69
我知道它没有正常工作,我想说的是写三个参数可以解决问题,然后他可以调整事情该如何完成。 - ThomasG2201
无法运行:RangeError:超出最大调用堆栈大小 - Kaiser69
笑死,我的评论只是想解释为什么会出现这个 TypeScript 警告。 - ThomasG2201

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接