我实际上想要一个只有固定数量项目的类型化数组——在下面的示例中,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 在这里比我们聪明。编译器可以看到您为
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
类型