Angular inputs Metadata Array
ID |
javascript.angular_inputs_metadata |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
low |
Resource |
Best Practice |
Language |
JavaScript |
Tags |
angular, best-practice, framework, maintainability |
Description
Reports an inputs array in @Component or @Directive metadata — the string-typed alternative to decorating the property itself:
import { Component } from "@angular/core";
// Bad
@Component({ selector: "app-field", template: "", inputs: ["label", "value: val"] })
export class FieldComponent {
label = "";
value = "";
}
import { Component, Input } from "@angular/core";
// Good
@Component({ selector: "app-field", template: "" })
export class FieldComponent {
@Input() label = "";
@Input() value = "";
}
Rationale
The array names its properties in strings, so nothing connects an entry to the member it is about:
-
Renaming or deleting the property leaves the entry behind and still compiling. The input then silently stops working, or Angular writes an incoming value onto a property the class no longer declares.
-
Nothing in the class says the property is public API, so the next reader has to open the decorator to find out which of the members a template may set.
-
A refactoring tool cannot follow the link, so a rename that looks safe is not.
@Input() states the same thing on the property, where the compiler sees both halves at once and a rename carries the declaration with it.
Remediation
Move each entry onto its property and delete the array:
import { Component, Input } from "@angular/core";
@Component({ selector: "app-field", template: "" })
export class FieldComponent {
@Input() label = "";
@Input() val = "";
}
An entry written as "value: val" also declares an alias. Prefer renaming the property to the name the template should use rather than carrying the alias over — see javascript.angular_input_alias.