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.

Inputs typed as enums and Ivy with strictTemplates

See original GitHub issue

🚀 feature request

Relevant Package

This feature request is for @angular/compiler

Description

If an input is typed as a TypeScript enum, than Ivy (using strictTemplates) is throwing an error when passing the enum value to the input.

For example the mode in TableComponent:

export enum TableMode { 
  HORIZONTAL = 'horizontal',
  VERTICAL = 'vertical'
}
@Component({
  selector: 'my-table',
  template: '{{ mode }}'
})
export class TableComponent {
  @Input() mode: TableMode;
}
@Component({
  selector: 'my-app',
  template: '<my-table mode="horizontal"></my-table>',
})
export class AppComponent {
}

Repro https://ng-run.com/edit/kIWtfjISbf5rmPS1sseQ

Describe the solution you’d like

In a perfect world that would compile without errors even with strictTemplates enabled (as it was with VE of course, as there was no type checking).

After discussing with @JoostK , it appears this issue is expected as TS does not allow @Input() mode: TableMode = 'horizontal', so it might not be fixable on the framework side.

This issue is here to document this behavior and the possible workaround, and to be able to point library authors to it, so they favor other types than enums for their inputs.

Describe alternatives you’ve considered

It is possible to workaround it by using:

@Component({
  selector: 'my-app',
  template: '<my-table [mode]="TableModel.HORIZONTAL"></my-table>',
})
export class AppComponent {
  TableMode = TableMode;
}

which is of course a bit cumbersome.

It is also possible to deactivate the type checking on the value by wrapping it with $any():

@Component({
  selector: 'my-app',
  template: '<my-table [mode]="$any('horizontal')"></my-table>',
})
export class AppComponent {
}

but this is obviously not ideal.

Another alternative is to not use enums when possible, and favor a union type for the input:

@Component({
  selector: 'my-table',
  template: '{{ mode }}'
})
export class TableComponent {
  @Input() mode: 'horizontal'|'vertical';
}

update (april 2021): based on @groetzi suggestion to use TS 4.1 template literal types, we can also use (untested):

@Component({
  selector: 'my-table',
  template: '{{ mode }}'
})
export class TableComponent {
  @Input() mode: `${TableMode}`;
}

Issue Analytics

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

github_iconTop GitHub Comments

2reactions
JoostKcommented, Feb 12, 2020

I was thinking of a way to workaround this in the template type checker by generating an indexed access of the enum type, like TableMode['horizontal'] but TypeScript doesn’t check whether that index is actually present.

But even if it did, providing a string to an enum that happens to use that same string representation is rather error-prone. The enum’s values are allowed to change without affecting its public API so referring to the values of an enum is not guaranteed to stay accurate (note: that’s only true for non-const enums).

As such, I believe the template type checker is rightfully complaining about the template 😉 The cleanest approach that avoids this issue is to use type unions instead of enums, as suggested in the issue description. However, if you’re dealing with a library that does use an enum for an input, the first alternative in the issue description can be used instead.

1reaction
mlc-mlapiscommented, Feb 12, 2020

@cexbrayat What confuses me is the fact that repeated use of the same string literals in code is not a good pattern. That’s why you have that enum to eliminate it. So what is wrong on <my-table [mode]="TableModel.HORIZONTAL"></my-table> where you strictly use still the same enum? It’s still far better, even you need to define public property TableModel explicitly.

Read more comments on GitHub >

github_iconTop Results From Across the Web

strictTemplates causing weird issues - angular - Stack Overflow
I have an Angular application and want to add strictTemplate checking, ... So the type annotation makes it so that only enums are...
Read more >
Angular 9's Best Hidden Feature: Strict Template Checking
When strictTemplates is true, Angular 9 and the Ivy compiler verify that hero is a valid model of type Hero , and that...
Read more >
What's new in Angular v12 - This Dot Labs
Ivy has been released from Angular 9 and has become the default in the Angular App from Angular 10. It is fast, easy...
Read more >
Using TypeScript Enums in Angular Templates | Wijmo
Enums allow you to define a set of named constants that are tied to and can ... Here, we'll discuss Enum-type properties in...
Read more >
Template type checking - Angular
If you want to use strictTemplates and strictNullChecks together, opt out of strict null type checking specifically for input bindings using ...
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