question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Ivy template type checking doesn't narrow types in output positions

See original GitHub issue

🐞 bug report

Scope

@angular/compiler-cli Specifically: Ivy template type checking

Is this a regression?

No.

Description / Reproduction

Given a template such as

<some-component
    *ngIf="myVar"
    [anInput]="myVar.otherVal"
    (anOutput)="myFunc(myVar)"
></some-component>

And the owning component class contains

    public myVar?: {otherVal: number};
    public myFunc(aDefinedVal: {otherVal: number}) {}

The type checker will correctly know that myVar.otherVal is a safe operation under strictNullChecks because of the *ngIf, but the checker will incorrectly throw an error on the myFunc(myVar), claiming that myVar is of type {otherVal: number} | undefined which is not assignable to type {otherVal: number} (diagnostic code NG2345).

🌍 Environment

@angular/common”: “9.0.0-rc.11”, “@angular/compiler”: “9.0.0-rc.11”, “@angular/compiler-cli”: “9.0.0-rc.11”, “@angular/core”: “9.0.0-rc.11”,

Compiled using Bazel and --define=angular_ivy_enabled=True

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:8
  • Comments:6 (5 by maintainers)

github_iconTop GitHub Comments

3reactions
DavidANeilcommented, Jan 31, 2020

I dropped the following test into packages/compiler-cli/test/ngtsc/template_typecheck_spec.ts to verify the issue.

fit('ngIf should narrow on output types', () => {
  env.write('test.ts', `
    import {Component, Directive, NgModule, EventEmitter, Output} from '@angular/core';

    @Component({
      selector: 'test',
      template: '<div *ngIf="prop" dir (foo)="func(prop)"></div>',
    })
    class TestCmp {
      prop?: string
      func(str: string) {}
    }

    @Directive({selector: '[dir]'})
    class TestDir {
      @Output() foo: EventEmitter<void>;
    }

    @NgModule({
      declarations: [TestCmp, TestDir],
    })
    class Module {}
  `);
  env.tsconfig(
    {fullTemplateTypeCheck: true, strictOutputEventTypes: true});
  const diags = env.driveDiagnostics();
  expect(diags.length).toBe(0);
  // console.error(diags[0].messageText);
});

The issue happens both with and without strictOutputEventTypes

2reactions
JoostKcommented, Feb 6, 2020

Hi @DavidANeil, thanks for the report and the testcase! I have a PR that implements Alex’s proposal to repeat the template guards within the event handlers, so their narrowing effect will be in effect.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Type-checking templates in Angular View Engine and Ivy
In this article we'll explore how Angular type-checks templates, review the difference between View Engine and Ivy type-checking and break down the process ......
Read more >
Can I do type-narrowing in an Angular template?
There is a way in Angular Ivy to allow type narrowing in a template with strict template checking. It's a little hacky but...
Read more >
Template type checking - Angular
Infers the correct type of local references to DOM elements, based on the tag name (for example, the type that document.
Read more >
Angular 9's Best Hidden Feature: Strict Template Checking
Find and report more errors than ever with Angular 9's Ivy compiler, strict template checking.
Read more >
Directive Type Checking - DEV Community ‍ ‍
Typescript enforces strict types and helps us make our codebase more resilient. Unfortunately, custom directives are not completely typed ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found