3

Why Typescript allow me to use any array element without forcing me to check if the index is valid?

Here is what I mean

function return_array(p:boolean):string[]{
    return (p) ? ['s'] : [];
}

const arr = return_array(false);
arr[30].toUpperCase();

This will obviously lead me to an error

Cannot read property 'toUpperCase' of undefined 

Is this by design or am I missing something?

Playground Link

Edit

The real function is something like:

function return_array(p:boolean):string[]{
    // querying the db, it can return an empty array. 
    return db_response;
} 
2
  • 4
    The length of the array varies at runtime and it's not something TypeScript should be checking against. You should probably perform a sanity check on arr[30] first before attempting to chain anything to it. Optional chaining operator and/or null coalescing operator are your best friends, e.g. a[30]?.toUpperCase(); Commented Mar 31, 2021 at 11:27
  • You can return a tuple [string] Commented Mar 31, 2021 at 11:33

3 Answers 3

3

By default, TS doesn't check if the value exists under a particular index in dynamic arrays (string[]). To ensure the type safety, you can do one of (or both):

  1. Narrow the return type to [string] | [] (since this is what your function is actually returning).
  2. Set noUncheckedIndexedAccess in your TS config (this will force you to checks for undefined elements anytime you're accessing an index).
Sign up to request clarification or add additional context in comments.

3 Comments

As far as I know, arrays in JavaScript are always dynamic (as with almost everything in JavaScript). I fail to see how your first point could solve the issue at hand. But I find your second point interesting; I didn't know about that compiler option, so I will certainly look into it. :)
@BartHofland “I fail to see how your first point could solve the issue at hand” Did you try the code? It will give you the error that you want. It uses a union of two tuple types to say that the returned array will have either 0 or 1 elements. So setting or accessing anything outside of those bounds is not allowed by TS.
@LindaPaiste . . . I must admit that I haven't tried the code. But after reading your explanation, it makes perfect sense to me now. Thanks.
0

your function is explicitly returning string[] and typescript believes it. here's what you could do: playground

1 Comment

My real function doesn't really use a boolean to know if the array it is empty or not. It was just a way. In general I am querying the DB and the array can be empty.
0

Based on the value of parameter p, your function return_array returns either an array containing a single element 's' (when p == true) or an empty array (when p == false).

You call return_array(false) and store the result in a variable called arr. That means, that arr will be an empty array.

Then you want to access the 31st element of that empty array (note that array indexes start at 0). That element is undefined, since the array has no elements at all.

You cannot call toUpperCase on undefined, since undefined and null have no members.

Note that TypeScript just compiles to JavaScript. And the above code is valid JavaScript. The following code would work fine as well:

const arr: string[] = [];
arr[30] = 's';

This will result in an array where arr[0] to arr[29] are undefined and arr[30] will be 's'.

TypeScript's behavior is correct. It should not override any behavior from JavaScript. It's simply valid to access an out-of-bounds element in a JavaScript array.

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.