Skip to content

Language service errors on possibly null binding when it's already checked #18248

Closed

Description

@cyrilletuzi

I'm submitting a...


[ ] Regression (a behavior that used to work and stopped working in a new release)
[X] Bug report  
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request => Please do not submit support request here, instead see https://github.com/angular/angular/blob/master/CONTRIBUTING.md#question

Current behavior

Given this component :

@Component({
  template: `<div *ngIf="data"><p>{{data.title}}</p></div>`
})
export class TestComponent {
  data: SomeObjectInterface | null;
}

The language service raises the error "The expression might be null" on data.title but it's already checked by *ngIf.

Expected behavior

Should not raise an error.

Environment


Angular version: 4.3.1
VS Code Angular Language Service extension 0.1.4

Activity

  1. cyrilletuzi commented on Aug 18, 2017

    @cyrilletuzi
    ContributorAuthor

    @chuckjaz Some news about this issue ?

  2. chuckjaz commented on Aug 18, 2017

    @chuckjaz
    Contributor

    This will not be addressed until 6.0 as it will require a breaking change to the NgIf declaration that will not be ready in time for 5.0.

    The template compiler does not know the runtime behavior of directives, including something as fundamental as *ngIf, therefore, there is currently no typing relationship that can be derived for data inside the template. This is similar to, for example, if you would have written the following in TypeScript:

    function ngIf(condition: boolean, cb: () => void) { if (condition) cb()) }
    ngIf(data, () => data.title);

    here (turn on strict null option to see the error).

    This will report that data could possibly be undefined in lambda because proving otherwise requires knowledge of the runtime behavior of ngIf.

    To do this we could change the declaration of NgIf to something like what is implied by this playground (turn on strict null checks and see that d is inferred to be of type string).

    This would be similar to rewriting the above as:

    function ngIf<T>(condition: T | null  | undefined, cb: (condition: T) => void) {
      if (condition) cb(condition);
    }
    
    ngIf(data, data => data.title);

    here

    The new type checker is scheduled for 5.1 but this will not be included in it. As this is a breaking change it cannot happen till 6.0.

  3. cyrilletuzi commented on Aug 18, 2017

    @cyrilletuzi
    ContributorAuthor

    Thanks for the detailed answer.

  4. added this to the Backlog milestone on Jan 23, 2018
  5. thw0rted commented on Feb 27, 2018

    @thw0rted

    Hi, does this also apply to the case of type narrowing inside the if-condition itself, or is that a separate issue?

    class Animal { }
    class Bird extends Animal { public wingCount: number; }
        
    @Component({
      template: `<div *ngIf="isBird(animal) && (animal.wingCount > 2)"><p>This is one crazy bird!</p></div>`
    })
    export class TestComponent {
      @Input() animal: Animal;
      isBird(a: Animal): a is Bird { return a instanceof Bird; }
    }
    

    In the current language service, the reference to animal.wingCount would be an error ("'Animal' does not contain such a member"), even though of course the AOT compiler gets through it just fine.

  6. cyrilletuzi commented on Apr 14, 2018

    @cyrilletuzi
    ContributorAuthor

    Closing this as there are no errors anymore.

    But for info, now it seems there is the opposite problem: object is not detected as potentially null when there is no *ngIf.

  7. thw0rted commented on Apr 16, 2018

    @thw0rted

    I don't think it's fixed on the templates, at least -- see my previous comment. I don't run the language service directly (I guess via tsc?) but in VS Code (Salsa), I still get warnings in statements that would compile cleanly in non-template (.ts file) context. In the above example, *ngIf="isBird(animal) && (animal.wingCount > 2) would have a red squiggle under animal.wingCount because wingCount is only defined on Bird and the language service doesn't treat isBird as narrowing the type, even though the actual compiler does.

    Would it be better to re-open this issue, or to open a new issue specific to errors in the template itself?

  8. nathanosdev commented on Jun 23, 2018

    @nathanosdev

    @thw0rted The plugin for VSCode is using an older version of the Angular language service, so it would be better to open an issue here instead: https://github.com/angular/vscode-ng-language-service

    See here: https://marketplace.visualstudio.com/items?itemName=Angular.ng-template

    This extension uses @angular/language-service@5.2.2-250c8da and typescript@2.6.2.

  9. fetis commented on Jul 2, 2018

    @fetis

    @cyrilletuzi I'm using the language service v6.0.6 in WebStorm and has this issue.

  10. inmogr commented on Nov 27, 2018

    @inmogr

    @chuckjaz im having the same issue here

    <div *ngIf="object">
    	{{ object.someField }}
    </div>
    

    Could you please assist?
    I'm using Angular 7.0.5 another note my object is of type Type | undefined still the error is showing as

    [Angular] The expression might be null
    
  11. yoosif0 commented on Mar 19, 2019

    @yoosif0

    I am having the same issue with version 7. I am currently adding ! in front of expressions even though I am using *ngIf. I think this hack is not clean.

  12. angular-automatic-lock-bot commented on Sep 14, 2019

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  13. locked and limited conversation to collaborators on Sep 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions