typescriptundefinedtyping

TypeScript ignores explicit undefined type annotation


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);

Playground Link


Solution

  • 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;
    

    Playground

    Another trick is to define your array with possible undefined members:

    const fooArray: {[i: number]: foo|undefined} = [{foo: {bar: {text: "hi"}}}];
    

    Playground

    You can even use a generic:

    type UnsafeArray<T> = {[i: number]: T|undefined};
    const fooArray: UnsafeArray<foo> = [{foo: {bar: {text: "hi"}}}];
    

    Playground

    All this is implied to work with "noUncheckedIndexedAccess": false