Make sure to activate the noUncheckedIndexedAccess
setting within the compilerOptions
section of your tsconfig.json
.
Once enabled, you will begin receiving TypeScript errors such as
Object is possibly 'undefined'.(2532)
for statements like these.
type List = { name: string }[]
const l: List = []
l[0].name // <-- error
l[0]?.name // <-- no error (ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining)
Interactive Playground
It's important to note that the noUncheckedIndexedAccess
option does not verify the length of your array; it serves as a reminder that the index being accessed may not exist.
If your array (and its elements) are intended to be immutable, you can also utilize const assertion:
const l = [{ name: 'foo' }] as const
l[0].name // no error
l[1] // error: Tuple type 'readonly [{ readonly name: "foo"; }]' of length '1' has no element at index '1'.(2493)
If you simply wish to have a fixed-length array with mutable elements in TypeScript 4.1 and above, you can achieve this by:
// based on - https://stackoverflow.com/a/52490977
type _TupleOf<T, N extends number, R extends unknown[]> = R['length'] extends N ? Readonly<R> : _TupleOf<T, N, [T, ...R]>
type Tuple<T, N extends number> = N extends N ? (number extends N ? T[] : _TupleOf<T, N, []>) : never
type List = Tuple<{ name: string }, 1>
const l: List = [{ name: 'foo' }]
l[0].name // no error
l[1] // error: Tuple type 'readonly [{ name: string; }]' of length '1' has no element at index '1'.(2493)