Content-Length: 289086 | pFad | http://github.com/angular/angular/issues/61754

E4 @switch can't narrow discriminate union through @let variable · Issue #61754 · angular/angular · GitHub
Skip to content

@switch can't narrow discriminate union through @let variable #61754

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
Harpush opened this issue May 29, 2025 · 7 comments
Open

@switch can't narrow discriminate union through @let variable #61754

Harpush opened this issue May 29, 2025 · 7 comments
Labels
area: compiler Issues related to `ngc`, Angular's template compiler compiler: template type-checking
Milestone

Comments

@Harpush
Copy link

Harpush commented May 29, 2025

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

core

Is this a regression?

No

Description

Given the following model:

interface TestA {
  type: 'a';
  name: string;
}

interface TestB {
  type: 'b';
  value: number;
}

type Test = TestA | TestB;

In typescript we can do:

const testType = test.type;
switch (testType) {
  case 'a':
    console.log(test.name);
    break;
  case 'b':
    console.log(test.value);
    break;
}

But in HTML this won't compile:

@let testType = test.type;
@switch(testType) {
  @case ('a') {
    {{test.name}}
  }
  @case ('b') {
    {{test.value}}
  }
}

Please provide a link to a minimal reproduction of the bug

https://stackblitz.com/edit/w1mfaabm?file=src%2Fmain.ts

Please provide the exception or error you saw

NG9: Property 'name' does not exist on type 'Test'.
  Property 'name' does not exist on type 'TestB'.

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

Angular 20

Anything else?

The reason for this is doing an exhaustive check in template:

@let testType = test.type;
@switch(testType) {
  @case ('a') {
    {{test.name}}
  }
  @case ('b') {
    {{test.value}}
  }
  @default {
    {{testType | exhaustiveCheck}}
  }
}
@JeanMeche JeanMeche added compiler: template type-checking area: compiler Issues related to `ngc`, Angular's template compiler labels May 29, 2025
@ngbot ngbot bot added this to the needsTriage milestone May 29, 2025
@JeanMeche
Copy link
Member

Fwiw this can be reproduced also with an @if block.

@let testType = test.type;
@if(testType == 'a') {
  {{test.name}} // errror 
}

@JeanMeche
Copy link
Member

JeanMeche commented May 29, 2025

So it looks like this one might me be somehow a typescript issue (a bit like #59215).

The TCB generates something like this

function _tcb1(this: { test: Test }) {
    if (true) {
        const _t1 = (((((this).test)).type));
        if (_t1 === "a") {
            (((((this).test)).name));
        }
    }
} 

The parenthesis seems to mess up the narrowing as you can see in this playground.

Playground demo.

Edit: Upstream issue microsoft/TypeScript#61784

@Harpush
Copy link
Author

Harpush commented May 29, 2025

@JeanMeche well guess I need to subscribe to the typescript issue :)
I always wonder why the TCB generate so many parenthesis... Seems redundant

@JeanMeche
Copy link
Member

I might need to defer to @JoostK (who is so much more knowledgable on that topic) for this question.

@crisbeto
Copy link
Member

We add comments after each node so we can map the error back to its source. The parentheses ensure that the comment gets associated with the intended node in the AST.

@Harpush
Copy link
Author

Harpush commented May 30, 2025

Ah that makes sense... Thanks for the explanation :)

@JoostK
Copy link
Member

JoostK commented May 30, 2025

Indeed, that is the reason. There's some more comments, e.g. to suppress diagnostics that would have been reported elsewhere (we sometimes have to repeat certain expression) and some comments specifically for the language service to identify code.

For source mapping you'd think that we could leverage source maps, and that would be a possibility except that TypeScript's ts.Printer API doesn't generate those.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: compiler Issues related to `ngc`, Angular's template compiler compiler: template type-checking
Projects
None yet
Development

No branches or pull requests

4 participants








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/angular/angular/issues/61754

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy