Reputation: 2036
I have a component with an Input defined as a custom type.
@Input() public labelSize: 'small' | 'normal' | 'large' = 'normal';
But apparently I can pass any kind of parameter to the component tag. I will never have any kind of error/warning.
<my-component labelSize="whatever"></my-component>
I can event pass a number
<my-component labelSize=12345></my-component>
I expected the typescript compiler or angular to give me some feedback on this kind of error.
I'm supposed to validate myself the type of all the Inputs of my components?
Any best practices?
Thanks
Upvotes: 4
Views: 1221
Reputation: 5413
The angular templates are HTML and are not in any way hooked into typescript for checking this. And even in typescript it's allowed to bypass the type declaration, e.g. this.labelSize = 'whatever' as any
.
In the end the code is still javascript. And in the templates is just like using plain javascript from the start.
If you really want to catch mismatches up front, some possible solutions are:
1. Validation
As already suggested, do a manual validation or use a validation library to specify constraints, e.g. https://validatejs.org/
By the way, you can also use a Pipe to add validation on the fly on any of your values and have more clarity on your html.
2. Config objects
You can capture the configuration of components where types are important in an object, as such
@Input() public config: {
labelSize: 'small' | 'normal' | 'large';
} = { labelSize: 'normal' }
and then bind the input to myCompConfig
:
<my-component [config]="myCompConfig"></my-component>
then in your controller where you use it
this.myCompConfig = { labelSize: 'whatever' } // error <- type is enforced now
3. TS for templates
You can use TS instead of HTML for templates, and assist it with some type info:
Share your type first
export type LabelSize = 'small' | 'normal' | 'large'
@Input() public labelSize: LabelSize = 'normal';
my-template.ts
const labelSize: LabelSize = 'whatever' // error <- type is enforced
export const template = `
<my-component labelSize=${labelSize}></my-component>`
`;
then in your component use it directly
import { template } from './my-template.ts';
@Component({ selector: 'something', template })
Note this can also be extracted into a factory-approach for creating parts of your temples, e.g. you can have a factory for creating this element based on a labelSize param (and this param can have type info).
Upvotes: 1