3

When the array is empty, TS does no type checking

My code here

type List = { name: string }[]

const l: List = []

// error
l[0].name

Is there any way to make TS check?How do I make TS check work?

2
  • 2
    TS doesn't know how many things you have in the array at runtime. Yes, it could here, but imagine the code was const l: List = getSomeListUsingUser(input); - then TS cannot know how many items the list contains. It can similarly not know if any particular place is empty, .e.g, [a, b, , d] will have length = 4 however l[2] doesn't exist. Commented Dec 1, 2021 at 10:15
  • 2
    Please consider noUncheckedIndexedAccess Commented Dec 1, 2021 at 10:16

1 Answer 1

6

Enable noUncheckedIndexedAccess in compilerOptions in your tsconfig.json.

After this you will start getting TS errors like Object is possibly 'undefined'.(2532) on such statements.

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)

Playground

Note that noUncheckedIndexedAccess option doesn't check the length of your array; it basically keeps reminding you that the index you are trying to access may not exist.


If your array (and its elements) are meant to be read only, you can also use 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 just want your array length to be fixed but the elements mutable, then in TS4.1 and above you can do this:

// 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)
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.