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
Type narrowing for NgSwitch and NgSwitchCase
#20780
Comments
|
Looking forward to see type guard support in language-service as well! My simple use case: interface Animal {
type: 'fish' | 'bird';
}
interface Fish extends Animal {
type: 'fish';
foo: string;
}
interface Bird extends Animal {
type: 'bird';
bar: string;
}
@Component({})
class MyComponent {
animal: Animal;
isFish(animal: Animal): animal is Fish {
return animal.type === 'fish';
}
isBird(animal: Animal): animal is Bird {
return animal.type === 'bird';
}
}Use case 1 <app-fish *ngIf="isFish(animal)" [foo]="animal.foo"></app-fish>
<app-bird *ngIf="isBird(animal)" [bar]="animal.bar"></app-bird>Use case 2 <ng-container [ngSwitch]="true">
<app-fish *ngSwitchCase="isFish(animal)"></app-fish>
<app-bird *ngSwitchCase="isBird(animal)"></app-bird>
</ng-container>Are both use cases covered? |
|
This would be a great addition, having an issue similar to case 2 that @dirkluijk posted. |
|
@chuckjaz any updates? Anyone working on this? Thanks |
|
Will this be solved in Ivy? |
|
No, this isn't solved by Ivy, if anything, Ivy will cause more people to realize how badly they need |
|
This would really clean up a lot of template code. How come this is such a low priority? |
|
It has 63 upvotes so seems like pretty needed feature. |
|
I just enabled strict type checking on templates, and I find it to be a highly beneficial feature; however, without type narrowing, you're really limited on the approach you can take when creating a component that accepts polymorphic data as an input, and conditionally render based on the type of data. |
|
I ended up updating our existing templates that used |
|
It may never be possible for The good news is you do not need to use a type guard function ( I've found this the most convenient way for displaying 'polymorphic' templates. No you won't get the nice 'switch' syntax or a Here's the updated types, note that In the component: Then in the template if I put This will result in an error for This won't work if |
|
@alxhub closed the issue above ☝️ saying it was a duplicate but I'm not sure it is so I'll jsut reiterate quickly here: I often end up using in a switch case the default to call a function which expects a parameter of type I think that if we could somehow replicate this behavior within the ngSwitch, that'd be a nice addition |
|
The above would be fantastic, I also do this a lot to check for exhaustiveness. In a larger codebase it can be tricky to consider all places that e.g. an enum is used so when you extend logic it is super helpful to have the compiler tell you where you missed something (error at compile time). E.g. class UnreachableCaseError extends Error {
constructor(val: never) {
super(`Unreachable case: ${val}`);
}
}
function getColorName(c: Color): string {
switch(c) {
case Color.Red:
return 'red';
case Color.Green:
return 'green';
default:
throw new UnreachableCaseError(c);
}
}It would be fantastic to have this in templates, too, so that we never end up with a piece of data that cannot be rendered |
|
Any news concerning this issue? Currently support for ngSwitch and else type narrow is the only thing that hold us back from enabling strict templates :( |
|
Is there possibility with new typescript satisfied operator? |
|
Come on it's 2023 |
|
5 years later, still not implemented :( Using functions as @dirkluijk commented is not an option for me as this functions will run each time the change detection runs and their pure purpose is to prevent type checking errors on build. |
|
I think this issue is not closed based on the ngswitch implementation, it just requires rewriting |
I've been wondering if this is true, |
|
Check discussion #50719, header
|
|
Although I like the answer of @dirkluijk There is a much simpler solution: export type ShapeType = 'circle' | 'square' | 'rectangle';
export interface Shape {
type: ShapeType;
}
export interface Circle extends Shape {
radius: number;
}
export interface Square extends Shape {
sideLength: number;
}
export interface Rectangle extends Shape {
width: number;
height: number;
}In the component i'm casting it to the shape. see my git repository for an example: |
|
One technique that can help: // In component.ts
// This type forces to create an object that always has exactly the same members & values as the original string union.
animalType: { [K in Animal['type']]: K } = {
bird: 'bird',
fish: 'fish'
}<ng-container [ngSwitch]="animal.type">
<app-fish *ngSwitchCase="animalType.bird"></app-fish>
<app-bird *ngSwitchCase="animalType.fish"></app-bird>
</ng-container> |
|
@baratgabor this is about |

Current behavior
No type narrowing is performed when using
NgSwitchandNgSwitchCase.Expected behavior
Narrow the types used in the
NgSwitchCasebased on the selection criteria.See #17953 (comment) and following for more details.
The text was updated successfully, but these errors were encountered: