Angular component validation rules that enforce naming conventions, selector validation, and architectural constraints for component classes and their metadata.
import { AbstractRule, IRuleMetadata, RuleFailure } from 'tslint';
import { SourceFile } from 'typescript';Enforces that classes decorated with @Component have the suffix "Component" (or custom) in their name.
/**
* Classes decorated with @Component must have suffix "Component" (or custom) in their name
* Follows Angular style guide: https://angular.io/styleguide#style-02-03
*/
export class ComponentClassSuffixRule extends AbstractRule {
static readonly metadata: IRuleMetadata;
static readonly FAILURE_STRING: string;
static validate(className: string, suffixList: string[]): boolean;
apply(sourceFile: SourceFile): RuleFailure[];
}Usage Examples:
TSLint configuration:
{
"rules": {
"component-class-suffix": true,
"component-class-suffix": [true, "Component", "View"]
}
}Valid component classes:
@Component({
selector: 'app-user'
})
export class UserComponent { }
@Component({
selector: 'app-dashboard'
})
export class DashboardView { } // When configured with custom suffixValidates component selector naming conventions and format.
/**
* Component selectors should follow specified naming conventions
* Follows Angular style guide for consistent selector patterns
*/
export class ComponentSelectorRule extends AbstractRule {
static readonly metadata: IRuleMetadata;
static readonly FAILURE_STRING: string;
apply(sourceFile: SourceFile): RuleFailure[];
}Usage Examples:
TSLint configuration:
{
"rules": {
"component-selector": [true, "element", "app", "kebab-case"],
"component-selector": [true, "element", ["app", "lib"], "kebab-case"]
}
}Valid component selectors:
@Component({
selector: 'app-user-profile' // element, app prefix, kebab-case
})
export class UserProfileComponent { }
@Component({
selector: 'lib-data-table' // element, lib prefix, kebab-case
})
export class DataTableComponent { }Limits the size of inline templates and styles in component decorators.
/**
* Enforces a maximum number of lines for inline templates and styles
* Promotes maintainability by encouraging external files for large templates
*/
export class ComponentMaxInlineDeclarationsRule extends AbstractRule {
static readonly metadata: IRuleMetadata;
static readonly FAILURE_STRING: string;
apply(sourceFile: SourceFile): RuleFailure[];
}Usage Examples:
TSLint configuration:
{
"rules": {
"component-max-inline-declarations": true,
"component-max-inline-declarations": [true, {"template": 5, "styles": 3}]
}
}Valid inline declarations:
@Component({
selector: 'app-simple',
template: `
<div>
<h1>{{ title }}</h1>
</div>
`, // Short template is acceptable
styles: [`
h1 { color: blue; }
`] // Short styles are acceptable
})
export class SimpleComponent { }Ensures Angular decorators are used in proper context and not misplaced.
/**
* Ensures decorators like @Input, @Output are used in proper context
* Prevents decorator misuse that could lead to runtime errors
*/
export class ContextualDecoratorRule extends AbstractRule {
static readonly metadata: IRuleMetadata;
apply(sourceFile: SourceFile): RuleFailure[];
}Validates that lifecycle methods are used in appropriate contexts.
/**
* Validates lifecycle methods are used in appropriate Angular contexts
* Ensures lifecycle hooks are only used in components, directives, etc.
*/
export class ContextualLifecycleRule extends AbstractRule {
static readonly metadata: IRuleMetadata;
apply(sourceFile: SourceFile): RuleFailure[];
}Enforces whitespace conventions in Angular templates and code.
/**
* Enforces consistent whitespace usage in Angular templates
* Maintains consistent formatting across Angular applications
*/
export class AngularWhitespaceRule extends AbstractRule {
static readonly metadata: IRuleMetadata;
apply(sourceFile: SourceFile): RuleFailure[];
}interface ComponentRuleOptions {
suffixList?: string[]; // For ComponentClassSuffixRule
maxLines?: {
template?: number;
styles?: number;
}; // For ComponentMaxInlineDeclarationsRule
selectorConfig?: [
boolean,
"element" | "attribute",
string | string[], // prefix(es)
"kebab-case" | "camelCase"
]; // For ComponentSelectorRule
}{
"rules": {
"component-class-suffix": [true, "Component", "Page"],
"component-selector": [true, "element", "app", "kebab-case"],
"component-max-inline-declarations": [true, {"template": 3, "styles": 5}],
"contextual-decorator": true,
"contextual-lifecycle": true,
"angular-whitespace": [true, "check-interpolation", "check-pipe"]
}
}