javascript - 在 typescript 中遍历可变元组

标签 javascript typescript recursion tuples typescript-generics

编辑:这个功能是作为 TypeScript 4.1 的一部分提供的,就像提到的 @jcalz 一样。
我想做一个通用类型,它接受一个元组并遍历它。我的第一种方法是递归,但我得到了 Type alias 'YourOperator' circularly references itself. .这是我尝试的最简单示例

type VariadicAnd<T extends any[]> = T extends [infer Head, ...infer Tail] ? Head & VariadicAnd<Tail> : unknown
在我的具体情况下,我还想转换 Head通过将它传递到另一个泛型类型中。例如:
type SimpleTransform<T> = { wrapped: T }
type VariadicAndWithTransform<T extends any[]> = T extends [infer Head, ...infer Tail]
  ? SimpleTransform<Head> & VariadicAndWithTransform<Tail>
  : unknown;
有趣的是,我的 IntelliSence 正在正确解析类型,但 typescript 编译器拒绝接受它。我想知道是否有另一种方法,或者是否有办法使我的递归工作。

最佳答案

如上所述,在引入对 recursive conditional types 的支持后,您的版本在 TypeScript 4.1 及更高版本中按原样运行。 .

type VariadicAndWithTransform<T extends any[]> = T extends [infer F, ...infer R]
  ? SimpleTransform<F> & VariadicAndWithTransform<R>
  : unknown; // no error

type Works = VariadicAndWithTransform<[{ a: 1 }, { b: 2 }, { c: 3 }]>;
/* type Works = SimpleTransform<{
    a: 1;
}> & SimpleTransform<{
    b: 2;
}> & SimpleTransform<{
    c: 3;
}> */
有一些变通方法可以诱使编译器允许 4.1 之前的类型,但它们不受官方支持。如果你需要递归条件类型,你应该升级你的 TypeScript 版本。

但是对于此处所需的类型函数,您不需要递归类型。这实际上是一件好事,因为递归类型对编译器的负担更大,并且递归限制相当浅。如果你使用以上版本的VariadicAndWithTransform<T>哪里T有几十个元素,即使在 TS4.1+ 中,您也会看到错误:
type Three = [{}, {}, {}];
type Nine = [...Three, ...Three, ...Three];
type TwentySeven = [...Nine, ...Nine, ...Nine]
type UhOh = VariadicAndWithTransform<TwentySeven>; // error!
// -------> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Type instantiation is excessively deep and possibly infinite.
非递归版本对于人类来说更难理解,但它使编译器更容易:
type VariadicAndWithTransform<T extends any[]> = {
  [K in keyof T]: (v: SimpleTransform<T[K]>) => void
}[number] extends ((v: infer I) => void) ? I : never
它的工作原理是 inferring in a conditional type来自逆变位置的联合(例如函数的参数),类似于 UnionToIntersection<T>从答案中输入 this question .
您可以验证它在上面的示例中的行为是否相同:
type Works = VariadicAndWithTransform<[{ a: 1 }, { b: 2 }, { c: 3 }]>;
/* type Works = SimpleTransform<{
    a: 1;
}> & SimpleTransform<{
    b: 2;
}> & SimpleTransform<{
    c: 3;
}> */
并且因为它不使用递归,所以它在处理更长的元组时没有问题:
type StillWorks = VariadicAndWithTransform<TwentySeven>;
/* type StillWorks = { wrapped: {}; } */    
Playground link to code

关于javascript - 在 typescript 中遍历可变元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67409468/

相关文章:

javascript - 解析Backbone.create方法的成功响应

javascript - Angular 5 上的推杆?

recursion - LISP 中的 wheres-waldo 函数

javascript - 动态更改特定单词的颜色

javascript - jQuery timepicker 抛出异常,该异常不是由我的代码触发的

angular - 如何设置 Angular 2 组件属性的默认值?

angular - 我的 NgRx 效果不工作,没有任何反应

python - 为用户输入递归调用函数

python - 从二叉树获取列表,TypeError

javascript - React onClick 事件不会触发 setState