When I specify a type of foo|undefined
for myConst
below, type inspection correctly tells me that myConst
has a type of foo|undefined
on that line. However, in the next line down, type inspection says that myConst
's type is simply foo
! Therefore, TypeScript does not require me to access its fields with a ?.
operator, and I can trigger a runtime exception. Why is this? Is there any way to make TS respect the explicitly-added undefined
type?
type foo = {
foo?: {
bar? : {
text: string
}
}
};
const fooArray: foo[] = [{foo: {bar: {text: "hi"}}}];
// type inspection tells me that type is correctly set to "foo|undefined"
const myConst: foo|undefined = fooArray[1];
// myConst type here is just "foo", not "foo|undefined". Where'd the "undefined" go?
// Causes runtime error: Cannot read properties of undefined (reading 'foo')
const message = myConst.foo?.bar?.text
// never executes
console.log(message);
The problem that the assignment narrowing is in action as explained by @jcalz. To set the type explicitly use type assertion:
const myConst = fooArray[1] as foo|undefined;
Another trick is to define your array with possible undefined
members:
const fooArray: {[i: number]: foo|undefined} = [{foo: {bar: {text: "hi"}}}];
You can even use a generic:
type UnsafeArray<T> = {[i: number]: T|undefined};
const fooArray: UnsafeArray<foo> = [{foo: {bar: {text: "hi"}}}];
All this is implied to work with "noUncheckedIndexedAccess": false