typescript 使用空元组创建元组的联合,而类型从未出现在forEach中

hfyxw5xn  于 2023-05-19  发布在  TypeScript
关注(0)|答案(1)|浏览(161)

我实际上想要一个类型化的数组,它只会有一定数量的项目-在下面的例子中,0,3或8。
但是,由于[],调用forEach或类似函数时的内容类型最终为never

type O = {prop:number}
type T = []|[O,O,O]|[O,O,O,O,O,O,O,O]

let t:T = []

t.forEach(v=>{
    v.prop // <- error, v is type never
})

该方法的原因是允许TS更积极地进行阵列索引访问检查,例如

t[0].prop += 1 // ! t[0] is type O|undefined

这可能有点傻,但我踩到了自己的脚,因为T很少使用[],而且TS数组访问是允许的。如果我知道它总是空的,长度为x或y,我想这将是一个简单的安全,只是规范它。

c9x0cxw0

c9x0cxw01#

编辑:

似乎根本不需要变通方法。错误的原因是TypeScript在这里比我们聪明。编译器可以看到你给t分配了一个空数组,并且 * 忽略 * 你给t的显式类型。有一个与t相关联的 * 隐藏 * 类型信息,这使得它的类型只是[]而不是T
我们可以通过类型Assert来停止这种行为。

let t: T = [] as T

t.forEach(v=>{
    v.prop // number
})

错误消失了。
只有在这种情况下才需要Assert,因为您为t分配了一个文字值。如果t的值确实未知,因为它是在运行时生成的或通过参数传递的,则不需要这样做。
Playground
一个可能的解决方法是 * 不 * 使用[]类型来表示空数组。相反,使用O[]并将其与{ length: 0 }相交。

type T = (O[] & { length: 0 }) | [O,O,O] | [O,O,O,O,O,O,O,O]

分配不同长度的数组仍然像以前一样工作。

// valid
let t: T = []
t = [{prop: 0}, {prop: 0}, {prop: 0}]
t = [{prop: 0}, {prop: 0}, {prop: 0}, {prop: 0}, {prop: 0}, {prop: 0}, {prop: 0}, {prop: 0}]

// invalid
t = [{ prop: 0 }]

forEach中的错误消失了。

t.forEach(v => {
    v.prop // number
})

Playground
一种更简洁的方法可能只是在将t用于.forEach之前检查t是否为空。

let t: T = [] as T

t.length !== 0 && t.forEach(v=>{
    v.prop // number
})

TypeScript足够智能,可以通过检查lengtht类型中排除[]类型。
Playground

相关问题