I effectively would like a typed array that will only ever have a set number of items — in the example below, 0, 3, or 8.
However, the type of the contents when calling forEach or similar ends up being never due to the [].
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
})
A reason for the approach is to allow TS to be more aggressive with array index access checking, e.g.
t[0].prop += 1 // ! t[0] is type O|undefined
This may be a bit silly but I stepped on my own foot because T is [] very infrequently and TS array access is permissive. Given I know it's always either empty, length x, or length y, I figured it'd be an easy safety to just spec it.
Edit:
It seems like the workaround is not needed at all. The reason for the error is that TypeScript outsmarts us here. The compiler can see that you assigned an empty array to
tand ignores the explicit type you gavet. There is hidden type information associated withtwhich makes its type just[]and notT.We can stop this behavior with a type assertion.
And the error is gone.
The assertion is only needed in this case because you assigned a literal value to
t. If the value oftis truly unknown because it is generated at runtime or passed via argument, this is not needed.Playground
One possible workaround could be to not use the
[]type to represent an empty array. Instead, use anO[]and intersect it with{ length: 0 }.Assigning arrays of various lengths still works as before.
And the error in the
forEachis gone.Playground
A cleaner approach would probably just to check if
tis empty before using it for the.forEach.TypeScript is smart enough the exclude the
[]type from the typetby checking thelength.Playground