创建元组与空元组的并集,而类型永远不会出现在 forEach 中

问题描述 投票:0回答:1

我实际上想要一个只有固定数量项目的类型化数组——在下面的示例中,0、3 或 8。

但是,由于

never
.
,调用forEach或类似内容时的内容类型最终为
[]

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,我认为只要指定它就很安全。

typescript tuples union typescript-never
1个回答
3
投票

编辑:

似乎根本不需要解决方法。错误的原因是 TypeScript 在这里比我们聪明。编译器可以看到您为

t
分配了一个空数组,并且 ignores 您给
t
的显式类型。有与t相关的
hidden
类型信息,这使得它的类型只是
[]
而不是
T

我们可以通过类型断言来阻止这种行为。

let t: T = [] as T

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

错误消失了。

只有在这种情况下才需要断言,因为您为

t
分配了文字值。如果
t
的值确实未知,因为它是在运行时生成的或通过参数传递的,则不需要这样做。

游乐场


一种可能的解决方法是 not 使用

[]
类型来表示空数组。相反,使用
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
})

游乐场


更简洁的方法可能只是在将

t
用于
.forEach
之前检查它是否为空。

let t: T = [] as T

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

TypeScript 足够聪明,通过检查

[]
.
 从类型 
t
 中排除 
length

类型

游乐场

© www.soinside.com 2019 - 2024. All rights reserved.