Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript: accessing an array element does not account for the possibility of undefined return values

Tags:

typescript

The following passes the Typescript type checker (v2.9.1), but throws a TypeError at run time.

interface Item { id: string } const list: Item[] = [{ id: 'a' }, { id: 'b' }]; const item = list[3]; // type: Item const itemId = item.id; // type: string 

Given that accessing an element in a typed array could always return undefined, shouldn't item be item: Item | undefined, which would force you to do a null check?

Even more surprisingly to me, the following also type checks:

const item2: Item | undefined = list[3]; const item2Id = item2.id; 

though casting the returned value does successfully fail the type check:

const item3 = list[3] as Item | undefined; const item3Id = item3.id; // [ts] Object is possibly 'undefined'. 

Creating an explicitly typed accessor function also catches the undefined case, but adds unnecessary overhead:

const getItem1 = (index: number, items: Item[]): Item | undefined => items[index]; const item3 = getItem1(3, list); const item3Id = item3 && item3.id; 

Is this a known limitation of typescript? Are there recommended patterns or libraries for handling this case?

like image 302
James Conkling Avatar asked Jun 01 '18 16:06

James Conkling


People also ask

Why is my array undefined TypeScript?

The value 'undefined' denotes that a variable has been declared, but hasn't been assigned any value. So, the value of the variable is 'undefined'.

Why is array find returning undefined?

The Array. find() method returns an undefined value if the condition implemented in the callback function is never satisfied or you haven't returned a value from the callback function. To solve this, use a type guard to check if find returned a value before accessing properties or methods.

How do you handle undefined in TypeScript?

To make a variable null we must assign null value to it as by default in typescript unassigned values are termed undefined. We can use typeof or '==' or '===' to check if a variable is null or undefined in typescript.

Does find() return undefined?

Array.prototype.find() The find() method returns the first element in the provided array that satisfies the provided testing function. If no values satisfy the testing function, undefined is returned.


1 Answers

PRE-TS4.1 ANSWER:

You have discovered that index signatures don't add | undefined to the element type the way that optional properties do. It has been suggested at microsoft/TypeScript#13778 to create a compiler option that would do this. You can read the comments in that suggestion; they link to other issues, but the consensus is that the high false positive rate would make it nearly useless.

It is also mentioned that you have the ability to manually add | undefined to the element type:

const list: (Item | undefined)[] = [{ id: 'a' }, { id: 'b' }]; 

which will behave as you expect, without affecting the whole language.


UPDATE for TS 4.1:

TypeScript 4.1 introduced a --noUncheckedIndexedAccess compiler flag that implements the suggestion in microsoft/TypeScript#13778 to account for undefined in this way. Note that the feature will not be enabled as part of the --strict set of compiler options and is being called "pedantic index signatures" because it will end up complaining about the possibility of undefined in situations where programmers might not expect or desire it.

like image 135
jcalz Avatar answered Oct 07 '22 12:10

jcalz