Home > Net >  How to check if optional object property exists?
How to check if optional object property exists?

Time:12-07

I'm having trouble getting TypeScript to recognise that an optional property of an object is defined.

type OuterKeys = 'a' | 'b';

type Inner = {
    value: '';
}

type Outer = Partial<Record<OuterKeys, Inner>>;

const thisGivesError = (key: OuterKeys, outer: Outer) => {
    if (outer[key]) {
        console.log(outer[key].value);
    }
}

Even though I explicitly check if outer[key] is defined, I'm getting error when trying to access outer[key].value: Object is possibly 'undefined'.

How can I work around it? The only way I found is assigning outer[key] to a variable and having another if, like below. Is this the only way to go?

const thisWorks = (key: OuterKeys, outer: Outer) => {
    const o = outer[key];
    if (o) {
      console.log(o.value);
    }    
}

The playground with the code can be found here

Edit: I don't want to use ! operator, as it feels like a workaround - why would I tell TypeScript that this value is set using non-null assertion, if I already checked for its existence with if? Same for .? - I already have the if, so this value for sure exists and is not optional.

CodePudding user response:

At this point, after checking for outer[key] being truthy, it's safe to go with non-null assertion:

if (outer[key]) {
    console.log(outer[key]!.value);
}

Though I don't know how to make TypeScript figure it out on its own.

CodePudding user response:

That's #10530, currently TS doesn't narrow down on indexed access.

CodePudding user response:

Because the inner object which holds the value is never specified to not be undefined. You can fix this by simply adding a question mark.

Ex adding a question mark:

const thisGivesError = (key: OuterKeys, outer: Outer) => {
    if (outer[key]) {
        console.log(outer[key]?.value);
    }
}

CodePudding user response:

You can make use of object?.key operator. You can learn more about it here.

Your final code will be:

const thisWorks = (key: OuterKeys, outer: Outer) => {
  if (outer[key]) {
    console.log(outer[key]?.value);
  }    
}
  • Related