javascript - Typescript:两个泛型数组的笛卡尔积导致推断出的类型错误
我在 Typescript 中写了一个简单的笛卡尔积实现,但推断的类型不是我预期的:
export function cartesianProduct<X, Y> (a: X[], b: Y[]): Array<[X, Y]> {
return a.flatMap(x => b.map(y => [x, y]));
}
如你所见,推断的类型是 (X | Y)[][] 而不是 [X, Y][]。这对我来说看起来很奇怪,因为 [x, y] 应该具有类型 [X, Y](x 是 X 类型,y 是 Y 类型)。有人知道我为什么会得到这个类型错误以及如何解决吗?
答案#1
TypeScript 通常会将数组字面量如 [x, y] 推断为数组类型,而不是元组类型。如果你想改变这一点,你需要为类型检查器提供上下文,使其以不同的方式推断类型。有多种方法可以实现这一点(例如使用 const 断言,或者使用 as 操作符进行类型断言,或者通过手动为 map 指定泛型类型参数,如 map<[X, Y]>)。
目前我最推荐的方法是使用 satisfies 运算符;如果你写 expr satisfies Type,它会告诉编译器使用 Type 作为推断 expr 类型的上下文。如果它能推断出一个兼容的类型,它就会这么做;否则它会产生一个错误,因此 satisfies 运算符在类型安全性上是类型断言所不具备的。
所以你所需要做的就是这个:
function cartesianProduct<X, Y>(a: X[], b: Y[]): Array<[X, Y]> {
return a.flatMap(x => b.map(y => [x, y] satisfies [X, Y]));
}
而且它有效。
代码的 Playground 链接
答案#2
Typescript 对你的类型感到困惑。你的代码看起来像是你想要一个数组,该数组返回更多包含 X 和 Y 混合的数组。然而,看起来你想要的是一个成对的数组,即 [X, Y]。
要修复你的错误,你必须定义内部数组应为 [X, Y]。像这样:
export function cartesianProduct<X, Y>(a: X[], b: Y[]): Array<[X, Y]> {
return a.flatMap((x: X) => b.map((y: Y) => [x, y] as [X, Y]));
}
