Nate Glenn
Nate Glenn

Reputation: 6744

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

Upvotes: 2

Views: 81

Answers (2)

Alexander Nenashev
Alexander Nenashev

Reputation: 23602

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

Upvotes: 1

PerfectM1nd
PerfectM1nd

Reputation: 63

To not ignore possibly undefined values from an array (or any object), add this to your tsconfig.json:

"noUncheckedIndexedAccess": true

Docs reference

Upvotes: 0

Related Questions