A comprehensive static code analysis tool for Angular TypeScript projects that implements TSLint rules enforcing Angular's official style guide.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
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"]
}
}Install with Tessl CLI
npx tessl i tessl/npm-codelyzer