网站搜索

typescript - Array.flat(Infinity) 的正确类型定义


我了解了新的 Array.flat 方法,并想用它来尝试一下,但返回的类型不是期望的。

const hello = [1, 2, [3], [[4]]]

const x = hello.flat(Infinity)

这将 x 的类型设置为:

const x: (number | number[] | number[][])[]

我怎样才能让它是 number[]?

答案#1

我猜你一定在使用 TypeScript 3.9 的测试版,并带有 Array.flat() 的新类型定义。这里的主要问题是 TypeScript 目前没有对应于 Infinity 的数字字面量类型(参见 microsoft/TypeScript#32277,有关添加此类型的开放建议)。

目前,在 TypeScript 中,Infinity 的类型只是 number。所以编译器无法知道 array.flat(Infinity) 会返回尽可能平坦的数组;相反,它把它当作你调用了 array.flat(num),其中 num 是某个 number 类型的表达式。这意味着编译器无法知道最终数组的平坦程度,最终会给你各种可能的扁平化深度的联合类型:

const z = [[[[[[0 as const]]]]]].flat(Infinity);
// const z: (0 | 0[] | 0[][] | 0[][][] | 0[][][][] | 0[][][][][])[]

在 microsoft/TypeScript#36554 的评论中提到了 flat() 的这个问题,该问题作为一个集合,收集了目前在 TypeScript 中表现不完美的数组方法的使用案例。如果你真的在意这个问题,你可能想点赞 👍,让大家知道这个使用案例正在使用中。

我建议你暂时只传入一个较大的数值常量,其类型可以表示为数值字面量。新的类型定义只有大约 20 深度是准确的,所以你不妨选择类似这样的值:

const y = [[[[[[0 as const]]]]]].flat(20);
// const y: 0[]

const x = hello.flat(20); // number[]

好的,希望有帮助;祝你好运!

代码的 Playground 链接