Search code examples
angulartypescriptoptional-chaining

optional chaining in Angular Template


Compiled with problems:X
ERROR
src/app/components/users/users.component.html:2:22 - error TS2532: Object is possibly 'undefined'. 

2 <ul *ngIf="loaded && users?.length > 0">
                       ~~~~~~~~~~~~~~~~~
  src/app/components/users/users.component.ts:6:16
    6   templateUrl: './users.component.html',
                     ~~~~~~~~~~~~~~~~~~~~~~~~
    Error occurs in the template of component UsersComponent.

This is my error. I have been looking around whithout much luck. My experience with angular or typescript is very limited. I am actualy following a udemy course. This is the first time I am encountering "Optional Chaining" so I might be overlooking something obvious.

The code that produces the issue is fairly simple

<h2>Users</h2>
<ul *ngIf="loaded && users?.length > 0">
  <li *ngFor="let user of users">
    <h3>{{ user.firstName }} {{ user.lastName }}</h3>
    <ul *ngIf="showExtended">
      <li>age: {{ user.age }}</li>
      <li>Address: {{ user.address.street }} {{ user.address.city }} {{ user.address.state }}</li>
    </ul>
  </li>
</ul>

The component.ts just provides a users[] But the coarse was trying to explain some sort of loading animation. Thats why the users[] sometimes is not loaded from the start.

Any help is appreciated.


Solution

  • It seems to me that you're running in strict mode which is good, but for someone that just started with TS and Angular can be overwhelming.

    This line here users?.length > 0 throws an error because the users list can be undefined so in the strict mode you cannot compare undefined to a number (as per the error message in your console) and the safety operator is not enough to get rid of that error.

    If you know that the users list cannot be undefined, you can use the definite assertion operator ! like so

    users!.length > 0
    

    But the best option is to check that your list is not undefined before comparing the length and you can do it like so:

    !!users && users.length
    

    Your condition will also work like this:

    users?.length
    

    By not comparing it to a number, the error won't be thrown and now that expression covers null, undefined and 0 values.