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:
- Created 4 years ago
- Comments:6 (5 by maintainers)

Top Related StackOverflow Question
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.
@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 propertyTableModel explicitly.