user3717031
user3717031

Reputation: 193

Class property: "Object is possibly undefined" in TypeScript

This seems like a pretty straightforward typescript snippet:

class Example {
    private items: Record<string, number[]> = {}

    example(key: string): void {
        if (this.items[key] === undefined) {
            this.items[key] = []
        }
        this.items[key].push(1)
    }
}

but it's giving the following error for this.items[key].push(1):

Object is possibly 'undefined'.ts(2532)

This works:

this.items[key]?.push(1)

but I'd like to understand why the compiler doesn't respect the explicit undefined check.

Upvotes: 2

Views: 2144

Answers (1)

Sean W
Sean W

Reputation: 6608

Typescript is showing this error because you are not correctly checking if your variable is undefined. It appears that you're defining it before reaching the block but it could potentially not be defined.

This is why you should not disable noUncheckedIndexedAccess - in this case - it would introduce a place for a bug.

FYI - adding ? at the end of the key is telling ts that you know for a fact that the key is defined - don't check. It should be avoided if possible.

Not checking - you original check

    example(key: string): void {
        // this is checking before your push
        if (this.items[key] === undefined) {
            this.items[key] = []
        }
        // independent from previous check and still reachable even if the variable is undefined
        this.items[key].push(1)
    }

Checking

    example(key: string): void {
        const item = this.items[key];
        if (!item) {
            this.items[key] = [1]
        } else {
            item.push(1)
        }
    }

A side note when checking if a key exist a more reliable approach over just just check if it's undefined would be this.items.hasOwnProperty(key) or !(key in this.itmes) because a value could be undefined, which if checking for undefined would have an opposite result as you were expecting.

This doesn't apply to the example above because it's cast to a variable prior to checks so it can only be a string or undefined - it can't contain a value of undefined

Upvotes: 3

Related Questions