angular: extended diagnostic for non-nullable optional is wrong

Which @angular/* package(s) are the source of the bug?

core

Is this a regression?

No

Description

Having the case below produces the warning for optional chain operation. Because of ! it will always return a boolean to the input. Relates to the new feature https://github.com/angular/angular/pull/46686 https://github.com/angular/angular/issues/44870

Also can we have a angularCompilerOptions to disable this warnings?

First case:

optionalArrayElement: {a: 'value'}[] = [];
<button [disabled]="!optionalArrayElement[0]?.a"></button>

Second case:

enum MapKeys {
  A,
  B
}

 optionalMapElement: {[key: string]: {a: string}} = {[MapKeys.A] : {a: 'value'}};
<button [disabled]="!optionalMapElement[MapKeys.B]?.a"></button>

Please provide a link to a minimal reproduction of the bug

https://stackblitz.com/edit/angular-r3n3ec?file=src/app/app.component.ts

Please provide the exception or error you saw

warning NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator.

Please provide the environment you discovered this bug in (run ng version)

Angular CLI: 14.1.0
Node: 16.15.1
Package Manager: npm 8.13.2
OS: win32 x64

Angular: 14.1.0
... animations, cli, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router
... service-worker

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1401.0
@angular-devkit/build-angular   14.1.0
@angular-devkit/core            14.1.0
@angular-devkit/schematics      14.1.0
@schematics/angular             14.1.0
rxjs                            7.5.6
typescript                      4.7.4

Anything else?

No response

About this issue

  • Original URL
  • State: open
  • Created 2 years ago
  • Reactions: 26
  • Comments: 34 (11 by maintainers)

Commits related to this issue

Most upvoted comments

An example of how to suppress this check right now (it’s not obvious from previous comments):


  "angularCompilerOptions": {
    "extendedDiagnostics": {
      "checks": {
        "optionalChainNotNullable": "suppress"
      }
    }
  }

I’d also like to turn off this warning.


"angularCompilerOptions": {

    "strictNullChecks": false

  }

Please do not do this. strictNullChecks is not an Angular compiler option, and disabling the TypeScript option is definitely not recommended.

This particular rule can be disabled like any other extended diagnostic, as documented here: https://angular.io/extended-diagnostics#configuration. The rule name is optionalChainNotNullable, which is currently not yet included in the docs.

Tip: watch out for optional properties inside *ngIf blocks. If you’re checking if an optional property is truthy then references of that property inside that *ngIf block will always be truthy and thus the ?. operator is unnecessary. Example:

TS: user?: {firstName: string, lastName: string};

Template:

<div *ngIf="user">
    <div>{{user?.firstName}}</div> <!-- unnecessary -->
    <div>{{user.firstName}}</div> <!-- ok -->
</div>
"extendedDiagnostics": {
      "checks": {
        "optionalChainNotNullable": "suppress"
      }
    }

@e-oz Thank you work for me on the angular 14 version

I also think that this NG8107 warning is broken. For example:

  1. I have an optional templateForm property in my TS class of type UntypedFormGroup so its inferred types are UntypedFormGroup | undefined
Screenshot 2022-07-26 at 13 27 37
  1. Yet, Angular says that The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. which is incorrect since an optional property can possibly be undefined.
Screenshot 2022-07-26 at 13 30 13

@nunoarruda can you please share a runnable reproduction?


As for the indexed access false positive: this happens because TypeScript doesn’t include undefined in the type of an indexed access expression (foo[index] syntax), so the optional chaining operator appears unnecessary based on the type system. I think it makes sense not to report this diagnostic for indexed accesses.

I’d also like to turn off this warning.

"angularCompilerOptions": {
    "strictNullChecks": false
  }

Hello. Got the same problem all over my application where things can clearly be null or undefined but I receive the warning regardless. Two examples bellow:

s01 s02 s03 s04

Angular CLI: 14.1.0 Node: 16.13.1 Package Manager: npm 8.1.2 OS: win32 x64

Angular: 14.1.0 … animations, cdk, cli, common, compiler, compiler-cli, core … forms, material, material-moment-adapter, platform-browser … platform-browser-dynamic, router

Package Version

@angular-devkit/architect 0.1401.0 @angular-devkit/build-angular 14.1.0 @angular-devkit/core 14.1.0 @angular-devkit/schematics 14.1.0 @angular/flex-layout 14.0.0-beta.40 @schematics/angular 14.1.0 rxjs 7.5.6 typescript 4.7.4

I also think that this NG8107 warning is broken. For example:

  1. I have an optional templateForm property in my TS class of type UntypedFormGroup so its inferred types are UntypedFormGroup | undefined Screenshot 2022-07-26 at 13 27 37

  2. Yet, Angular says that The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator. which is incorrect since an optional property can possibly be undefined. Screenshot 2022-07-26 at 13 30 13

I meet the same bugThe left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator when I run the code <img src="{{ product?.imageUrl }}" class="detail-img"> where I would like to use it to avoid race condition

One of the possible solutions is to replace the product?.imageUr with product&&product.imageUrl. Thus, <img src="{{ product&&product.imageUrl }}" class="detail-img">

@ghovmand try koersel.noegletal?.antalKanIkkeFordeles

Got the same warning:

Warning: src/main/webapp/skattekoersel/koersel/components/beregning/beregning-noegletal/beregning-noegletal.component.html:87:23 - warning NG8107: The left side of this optional chain operation does not include 'null' or 'undefined' in its type, therefore the '?.' operator can be replaced with the '.' operator.

87           {{ koersel?.noegletal?.antalKanIkkeFordeles | number }}
                         ~~~~~~~~~

After I “fixed” the warning it, got following error:

Error: src/main/webapp/skattekoersel/koersel/components/beregning/beregning-noegletal/beregning-noegletal.component.html:87:33 - error TS2532: Object is possibly 'undefined'.

87           {{ koersel?.noegletal.antalKanIkkeFordeles | number }}
                                   ~~~~~~~~~~~~~~~~~~~~

@robleka the first case you mentioned is because you defined person!: (the ! is the non-null assertion operator). Replace the exclamation mark with a question mark (person?:) and the errors should go away.

(Regarding the second case, I think it’s because item is defined as CommonTypes.Any, which I’m guessing maps to any.)

optionalChainNotNullable does not work for me

Can verify that this did fix it for me. Seems to require at least angular 14.1.

optionalChainNotNullable does not work for me

I’d also like to turn off this warning.

Hmm I was investigating the issue a bit some more. It seems our types are wrong since how I did in the stackblitz. The warning is being displayed only if we put the ? and the type of b is only as array (updated description).

Don’t know if you want to include this as a bug.