When working with TypeScript, errors may be thrown such as "Object is possibly 'undefined'" specifically in relation to class variables rather than scope variables

When using TypeScript with strict mode enabled on the TypeScript playground, I encountered an interesting case:

type Foo = { a: number; b: number; }

class Bar {

    #a?: Foo;

    bar() {
        const a = this.#a?.a;
        if (!a) {return;}

        // Error: Object is possibly 'undefined'.
        const b = this.#a.b;
    }

    bar2() {
        const obj = this.#getFoo();

        const a = obj?.a;
        if (!a) {return;}

        // No error:
        const b = obj.b;       
        console.log(b);
    }

    #getFoo() : Foo | undefined {
        return undefined;
    }

}

I wonder why TypeScript correctly identifies that obj.b cannot be undefined in bar2(), but not for this.#a.b in bar(). Is there a logical explanation that I am missing?

In bar(), assigning const tmp = this.#a also compiles successfully.


UPDATE: It seems like the issue is related to the mutability of a variable. If I use let obj = this.#getFoo(), the error occurs for obj as well.

Answer №1

The TypeScript compiler cannot ensure that the value of this.#a remains unchanged between two property accesses. This uncertainty arises because TypeScript assumes that a class property's value can change unpredictably, even within consecutive lines of code.

However, in the bar2() method, assigning the value of obj to this.#getFoo() does not raise any issues because obj is a local variable whose value TypeScript can guarantee stays constant throughout the property accesses.

In your recent update, using let obj = this.#getFoo(), TypeScript detects a potential problem as it considers obj mutable and thus subject to change between property accesses. Consequently, an error is flagged for obj.

To resolve this issue, you can assign this.#a to a local constant variable like so:

bar() {
        const obj = this.#a; // <----Take note of this
        const a = obj?.a;
        if (!a) {return;}

        // Error: Object is possibly 'undefined'.
        const b = obj.b;
    }

TYPESCRIPT PLAYGROUND

Context References

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

utilize a static library designed for a variety of systems

I received the code for a paper from the author, but encountered some issues with static libraries (.a) that were compiled by the author. Initially, I faced an error: /usr/bin/ld: skipping incompatible ../lib/libmvvt.a when searching for -lmvvt /usr/bin/l ...

Leveraging arrays and objects for simulating data in Angular2

Here is a class I am working with: export class Character { id: number; name: string; portrait: string; abilities: array; equipment: array; statistics: object; money: number; description: string; } ...

Storing and retrieving user credentials across different applications using NativeScript and Angular 2

I am looking to store user credentials (username and password) in a Nativescript application. In another Nativescript application, I need to be able to retrieve these stored credentials. Unfortunately, I am unsure of how to accomplish this in Nativescript ...

Bringing in a React component compiled with Webpack

Currently, I am utilizing create-react-app ReactJs basic application generator alongside typescript that is transpiled by webpack. Upon importing the App.js component (which is the compiled App.tsx component) in the index.js file, an error pops up in the ...

When trying to fetch and structure JSON data in Angular 6, the console displays "undefined" as the output

I'm currently exploring how to retrieve JSON data from an API, parse it, map it to my custom type, and then showcase it in an Angular Material datatable. Despite my efforts, the console output indicates that the value is undefined. I haven't even ...

Establishing the context for the input template by utilizing ng-template, ng-container, and ngTemplateOutlet

I am facing a challenge with a customizable component that utilizes an ng-container to display either a default template or a template passed in as an input. The issue arises when I try to set the context of the passed-in template to the nesting component ...

Collaborating with various sequential asynchronous services

In my component, I am injecting multiple services, two of which provide lists of objects needed by a third service. The problem is that the asynchronous calls to these services are not always executed in order. Nesting the calls inside each other does not ...

Fixing the "Module not found" error in an Angular library using npm link

I'm currently working on creating an Angular wrapper for a Javascript library, but I've encountered a "Module not found" error. The Javascript library is still in development and has not been published to NPM yet. To work around this issue, I hav ...

linting tool promises there are no missing attributes

When utilizing a component that connects to 'redux' and requires properties to be passed, the linter complains about missing properties. Component1 interface Component1Props { id: number; users: any[]; } const Component1: React.FC<Com ...

Insert the template's content into my inline component

I am facing an issue with a template I have created. The template structure is as follows: <template> <my-body-component inline-component> <slot/> </my-body-component> </template> My goal is to make my-body-component ...

The challenges of type verification in Redux reducer

I'm currently facing two specific challenges with Typescript and the Redux reducer. Reducer: const defaultState = { selectedLocation: { id: 0, name: 'No Location' }, allLocations: [{ id: 0, name: 'No Location' }], sele ...

VueJS component fails to properly sanitize the readme file, as discovered by Marked

Could someone explain why the output from the compiledMarkdown function is not sanitized, resulting in unstyled content from the markdown file? <template> <div style="padding:35px;"> <div v-html="compiledMarkdown" ...

TypeScript requires that the `includes` function must have the same type parameter for both input and

When working with TypeScript, I've encountered an interesting dilemma regarding the use of the Array.Prototype.includes function. It seems that this function requires me to pass in the same type as in the original array, but isn't the purpose of ...

Introducing a fresh counter variable inside a for loop

I'm currently working on a project with google-apps-script. My goal is to copy a row multiple times based on the number specified in a certain cell within a spreadsheet. For example, if B2 contains the number 6, I want to duplicate that row 6 times. I ...

The specified type argument is not compatible with the ObservableInput<any> type

Struggling with an issue where the argument type (key:string) => Observable | PayloadType | is causing problems when trying to assign it to a parameter of type '(value: string, index: number) => ObersvableInput' return action$.pipe( fil ...

How can you optimize the storage of keys in JS objects?

Just pondering over this scenario: Consider a line definition like the one below, where start and end are both points. let ln = { s: {x:0, y:0}, e: {x:0, y:0}, o: 'vertical' } Now imagine having a vast array of lines, how can we sav ...

Examining Axios HttpService piping through a NestJS middleware in a unit test

A middleware function retrieves a JSON document from a microservice endpoint and appends it to the request. The good path test is successful, but I'm struggling to make the bad path test throw a ForbiddenException and stop it from invoking next(). W ...

FilterService of PrimeNg

Looking for assistance with customizing a property of the p-columnFilter component. I have managed to modify the filter modes and customize the names, but I am having trouble with the no-filter option. Has anyone found a solution for this? this.matchMo ...

Tips for resolving package conflicts while integrating Wagmi View into a React/Typescript application

I am facing an issue while attempting to incorporate wagmi and viem packages into my project. Currently, my project utilizes the react-scripts package with the latest version being 5.0.1, and Typescript is operating on version 4.9.5. However, upon trying ...

What could be the reason behind tsx excluding attribute names with "-" in them from being checked?

Why doesn't TypeScript check attributes with a hyphen in the name? declare namespace JSX { interface ElementAttributesProperty { props:any; // specify the property name to use } } class A{ props!:{p1:string} } const tsx = <A p1="&q ...