Typescript code that does not take into account the possibility of array elements returning undefined
P粉824889650
2023-08-24 12:15:44
<p>The following code passes in the Typescript type checker (v2.9.1), but throws <code>TypeError</code> at runtime. </p>
<pre class="brush:php;toolbar:false;">interface Item { id: string }
const list: Item[] = [{ id: 'a' }, { id: 'b' }];
const item = list[3]; // Type: Item
const itemId = item.id; // Type: string</pre>
<p>Considering that accessing an element in a typed array may always return <code>undefined</code>, <code>item</code> should be <code>item: Item | undefined</code> , which would force you to do a null check, shouldn't it? </p>
<p>What surprised me even more is that the following code also passed the type check: </p>
<pre class="brush:php;toolbar:false;">const item2: Item | undefined = list[3];
const item2Id = item2.id;</pre>
<p>Although casting the return value does cause the type check to fail: </p>
<pre class="brush:php;toolbar:false;">const item3 = list[3] as Item | undefined;
const item3Id = item3.id; // [ts] Object is possibly 'undefined'.</pre>
<p>Creating an explicitly typed accessor function can also capture the <code>undefined</code> situation, but it will add unnecessary overhead: </p>
<pre class="brush:php;toolbar:false;">const getItem1 = (index: number, items: Item[]): Item | undefined => items[index];
const item3 = getItem1(3, list);
const item3Id = item3 && item3.id;</pre>
<p>Is this a known limitation of Typescript? Is there any recommended pattern or library to handle this situation? </p>
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 in microsoft/TypeScript#13778 to 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 at microsoft/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.