Angular outputs Metadata Array
ID |
javascript.angular_outputs_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 outputs array in @Component or @Directive metadata — the string-typed alternative to decorating the emitter itself:
import { Component, EventEmitter } from "@angular/core";
// Bad
@Component({ selector: "app-editor", template: "", outputs: ["saved", "cancel: cancelled"] })
export class EditorComponent {
saved = new EventEmitter<void>();
cancel = new EventEmitter<void>();
}
import { Component, EventEmitter, Output } from "@angular/core";
// Good
@Component({ selector: "app-editor", template: "" })
export class EditorComponent {
@Output() saved = new EventEmitter<void>();
@Output() cancelled = new EventEmitter<void>();
}
Rationale
The array names its emitters in strings, so nothing connects an entry to the member it is about:
-
Renaming or deleting the emitter leaves the entry behind and still compiling. Every template listening on that output then silently stops receiving anything.
-
Nothing in the class says the emitter is public API, so the next reader has to open the decorator to find out which of the members a template may subscribe to.
-
A refactoring tool cannot follow the link, so a rename that looks safe is not.
@Output() states the same thing on the emitter, where the compiler sees both halves at once and a rename carries the declaration with it.
Remediation
Move each entry onto its emitter and delete the array:
import { Component, EventEmitter, Output } from "@angular/core";
@Component({ selector: "app-editor", template: "" })
export class EditorComponent {
@Output() saved = new EventEmitter<void>();
@Output() cancelled = new EventEmitter<void>();
}
An entry written as "cancel: cancelled" also declares an alias. Prefer renaming the emitter to the name the template should listen on rather than carrying the alias over — see javascript.angular_output_alias.