TypeScript with strict null checking - what about array access?
TypeScript 4.1 introduced a new compiler option - noUncheckedIndexedAccess. Among other things, it adds undefined
to array index access type.
Consider the following snippet (TS playground):
const items = [1,2,3]
console.log(items[1]?.toString(10))
console.log(items[2].toString(10))
Without noUncheckedIndexedAccess
, items[2].toString(10)
will be deemed valid, and invalid when the option is on. The items[1]?.toString(10)
will be valid when the option is on, just like in comment by Alex Neth in the older answer.
Found it :-).
tl;dr: It is a deliberate omission. Array access is very common in TypeScript code, and forcing a null/undefined check for every access was considered too cumbersome for developers.
Note that since TypeScript 4.1 this is configurable with the compiler option noUncheckedIndexedAccess
. See Klaster_1's answer for details.
The issue has been raised several times in discussions:
- issue #11122 - Array lookup should return T | undefined
- comment on PR 7140
- #6229 - Proposal: strict and open-length tuple types
The comment on PR 7140 has a nice rationale from Anders Hejlsberg (one of the core developers):
Indexing simply produces a value of the type declared in the matching index signature. Even if it is technically more correct, it would simply be too painful if we automatically added
undefined
to the type of every indexing operation.For example, every array element access would have to be accompanied by a non-null guard or a
!
assertion. I think that would become hugely irritating.
Personal comment: I think this is a reasonable decision. The problem is inherent with arrays - I don't think it's possible to prove (for the compiler) whether a given position is defined, since you can use calculated positions. So any warning would produce many false positives, and most devs would switch it off anyway.
Essentially, arrays provide more freedom to the developer than the compiler can check. If you want proper checking, the only solution I can see is to avoid direct array access, and use other data structures that provide more protection.