如何将 TypeScript 可变元组类型用于笛卡尔积函数?

2023-12-06

TypeScript 4.0 开始支持以下概念可变参数元组类型,一个很好的类型构造,可以用于例如串联函数。文档中的一个示例:

type Arr = readonly any[];

function concat<T extends Arr, U extends Arr>(arr1: T, arr2: U): [...T, ...U] {
  return [...arr1, ...arr2];
}

我感兴趣的是这种类型构造是否可以用于输入笛卡尔积功能。然后,该函数应从参数推断(混合)类型以生成其返回类型。所以如果我输入[number[], string[]]我希望输出的类型为[number, string][]。笛卡尔积的多种实现可以在这个线程,但没有一个是严格类型化的。这是一个例子:

const cartesian =
  (...a) => a.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat())));

我当前使用的实现不使用可变元组类型,并且需要显式类型转换:

const cartesian = <T extends any[]>(...arr: any[][]): T[] =>
  arr.reduce<T[]>(
    (a, b) => a.flatMap<T>(c => b.map<T>(d => [...c, d] as T)),
    [[]] as T
  );

const product = cartesian<[number, string]>([1, 2, 3], ['a', 'b', 'c']);

我正在寻找一种无需显式类型转换的解决方案,并且我认为可变元组类型可能是这里合适的类型构造。

Question

如何使用可变元组类型来推断笛卡尔积函数的类型?


我不认为可变元组类型实际上改善了我们输入的方式。自从支持以来,实际上可以输入此内容映射元组在 3.1 中添加(以前可能是可能的,但没有那么干净)。

在实际实现中您仍然需要类型断言,但调用站点将推断参数类型并生成正确的返回类型:

type MapCartesian<T extends any[][]> = {
  [P in keyof T]: T[P] extends Array<infer U>? U: never
}
const cartesian = <T extends any[][]>(...arr: T): MapCartesian<T>[] =>
  arr.reduce(
    (a, b) => a.flatMap(c => b.map(d => [...c, d] )),
    [[]] 
  ) as MapCartesian<T>[];

const product = cartesian([1, 2, 3], ['a', 'b', 'c']);

游乐场链接

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将 TypeScript 可变元组类型用于笛卡尔积函数? 的相关文章

随机推荐