The following code passes in the Typescript type checker (v2.9.1), but throws TypeError
at runtime.
interface Item { id: string } const list: Item[] = [{ id: 'a' }, { id: 'b' }]; const item = list[3]; // Type: Item const itemId = item.id; // Type: string
Considering that accessing an element in a typed array may always return undefined
, item
should be item: Item | undefined
, which would force you to do a null check, shouldn't it?
What surprised me even more is that the following code also passed the type check:
const item2: Item | undefined = list[3]; const item2Id = item2.id;
Although casting the return value does cause the type check to fail:
const item3 = list[3] as Item | undefined; const item3Id = item3.id; // [ts] Object is possibly 'undefined'.
Creating an explicitly typed accessor function can also capture the undefined
situation, but it will add 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? Is there any recommended pattern or library to handle this situation?
This is intentional behavior.View the long discussion on this issue on the TypeScript GitHub repository
Your
strictNullChecks
is off; try turning it on.TS 4.1 Update:
TypeScript 4.1 introduced a
--noUncheckedIndexedAccess
compiler flag that implements the suggestion made inmicrosoft/TypeScript#13778to account forthis case undefined
. Note that this feature is not enabled as part of the--strict
compilation option set, and is referred to as a "strict index signature" because it emits situations where the programmer may not want or expect Warning aboutundefined
.TS4.1 previous answer:
You've discovered that index signatures do not add
| undefined
to element types like optional properties do. The suggestion to create a compiler option to achieve this was made atmicrosoft/TypeScript#13778. You can read the comments in that suggestion; they link to other questions, but the consensus is that the high error rate almost makes it useless.also mentioned that you can manually add
| undefined
to the element type:This will work as you expect without affecting the entire language.