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?
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'.
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With