我不能把那段代码从Java脚本转换成打字脚本.

问题是转换...扩散运算符.

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

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

TS2556: A spread argument must either have a tuple type or be passed 至 a rest parameter.

如果我改变了

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

 next = calculateCombinationsTS(next, rest);

该函数给出了一个错误结果,因为REST是作为数组的数组传递的,而不是参数列表

Example of output:

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' ] 
]

推荐答案

有两个问题:

  1. 如果要为REST参数传递一系列数组实参,则REST参数必须是数组数组,而不仅仅是array.所以:...rest: any[][].TypeScrip不会抱怨这一点,因为您可以对any使用数组,但它更准确地反映了您正在做的事情.

  2. TypeScrip无法判断调用calculateCombinationsTS(next, ...more);是否会将next的参数传递给函数,即使您判断了rest.length,因此you知道它会这样做.您需要使用两个离散参数调用该函数,然后(可选)展开一个array.您可以通过从rest参数中获取第一个元素并显式传递它来修复它:

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

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

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

修复这两个问题的完整功能:

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

Runnable playground example从您的示例生成72个组合

Javascript相关问答推荐

Phaser框架-将子对象附加到Actor

React 17与React 18中的不同setState行为

TypeScript索引签名模板限制

google docs boldText直到按行执行应用脚本错误

从Node JS将对象数组中的数据插入Postgres表

如何从隐藏/显示中删除其中一个点击?

Angular 订阅部分相互依赖并返回数组多个异步Http调用

用JS从平面文件构建树形 struct 的JSON

TypeError:无法分解';React2.useContext(...)';的属性';basename';,因为它为空

400 bad request error posting through node-fetch

覆盖加载器页面避免对页面上的元素进行操作

如何防止ionic 输入中的特殊字符.?

Phaserjs-创建带有层纹理的精灵层以自定义外观

Clip-Path在网页浏览器(Mozilla、Edge、Chrome)上不能正常工作,但在预览版Visual Code Studio HTML、CSS、JS上却能很好地工作

如何压缩图像并将其编码为文本?

在将元素追加到DOM之前,createElement()是否会触发回流?混淆abt DocumentFragment行为

输入数据覆盖JSON文件

material UI自动完成全宽

检测带有委托的元素内部的点击,以及元素何时按其类名被选中

如何让noWrap在嵌套在Alert/AlertTitle组件中的排版组件中工作?