Skip to content

Angular

Zen Principles

5 principles across 3 categories, drawn from Angular Style Guide.

Correctness · 2 principles Performance · 2 principles Readability · 1 principle

Rule ID Principle Category Severity Dogma
angular-001 Components should opt into OnPush change detection Performance 7 ZEN-PROPORTIONATE-COMPLEXITY
angular-002 Type annotations should avoid any Correctness 8 ZEN-EXPLICIT-INTENT
angular-003 Manual subscriptions need an explicit lifecycle strategy Correctness 9 ZEN-STRICT-FENCES, ZEN-EXPLICIT-INTENT
angular-004 Component selectors should follow project naming conventions Readability 5 ZEN-UNAMBIGUOUS-NAME
angular-005 Feature routes should prefer lazy loading over eager component wiring Performance 6 ZEN-PROPORTIONATE-COMPLEXITY
angular-001 — Components should opt into OnPush change detection

OnPush keeps Angular component trees predictable and reduces unnecessary change detection work.

Universal Dogmas: ZEN-PROPORTIONATE-COMPLEXITY Common Violations:

  • Components should opt into OnPush change detection

Detectable Patterns:

  • re:@Component\(\{(?:(?!ChangeDetectionStrategy\.OnPush)[\s\S])*?\}\)

Recommended Fix

Add changeDetection: ChangeDetectionStrategy.OnPush to the component decorator.

angular-002 — Type annotations should avoid any

Using any bypasses Angular's TypeScript guarantees and hides template/data contract issues.

Universal Dogmas: ZEN-EXPLICIT-INTENT Common Violations:

  • Type annotations should avoid any

Detectable Patterns:

  • re::\s*any\b

Recommended Fix

Replace any with a domain interface, union, or unknown plus narrowing.

angular-003 — Manual subscriptions need an explicit lifecycle strategy

Bare subscribe() calls often leak when they are not paired with takeUntil, async pipe, or cleanup logic.

Universal Dogmas: ZEN-STRICT-FENCES, ZEN-EXPLICIT-INTENT Common Violations:

  • Manual subscriptions need an explicit lifecycle strategy

Detectable Patterns:

  • re:\.subscribe\(

Recommended Fix

Use the async pipe, takeUntilDestroyed(), or an explicit teardown path.

angular-004 — Component selectors should follow project naming conventions

Selector prefixes help keep large Angular workspaces consistent and collision-free.

Universal Dogmas: ZEN-UNAMBIGUOUS-NAME Common Violations:

  • Component selectors should follow project naming conventions

Detectable Patterns:

  • re:selector\s*:\s*[\"\'](?!app-|lib-)[^\"\']+[\"\']

Recommended Fix

Prefix selectors with an application or library namespace such as app- or lib-.

angular-005 — Feature routes should prefer lazy loading over eager component wiring

Lazy-loaded route boundaries help keep initial bundles small and feature areas isolated.

Universal Dogmas: ZEN-PROPORTIONATE-COMPLEXITY Common Violations:

  • Feature routes should prefer lazy loading over eager component wiring

Detectable Patterns:

  • re:path\s*:\s*[\"\'][^\"\']+[\"\']\s*,\s*component\s*:

Recommended Fix

Use loadChildren or loadComponent for feature routes when appropriate.

Detector Catalog

Correctness

Detector What It Catches Rule IDs
AngularNoAnyDetector Concrete detector binding for AngularNoAnyDetector angular-002
AngularSubscriptionLifecycleDetector Concrete detector binding for AngularSubscriptionLifecycleDetector angular-003

Performance

Detector What It Catches Rule IDs
AngularOnPushDetector Concrete detector binding for AngularOnPushDetector angular-001
AngularLazyRouteDetector Concrete detector binding for AngularLazyRouteDetector angular-005

Readability

Detector What It Catches Rule IDs
AngularSelectorPrefixDetector Concrete detector binding for AngularSelectorPrefixDetector angular-004
Principle → Detector Wiring
%%{init: {"theme": "base", "flowchart": {"useMaxWidth": false, "htmlLabels": true, "nodeSpacing": 40, "rankSpacing": 60}}}%%
graph TD
angular_001["angular-001<br/>Components should opt int..."]
angular_002["angular-002<br/>Type annotations should a..."]
angular_003["angular-003<br/>Manual subscriptions need..."]
angular_004["angular-004<br/>Component selectors shoul..."]
angular_005["angular-005<br/>Feature routes should pre..."]
det_AngularLazyRouteDetector["Angular Lazy<br/>Route"]
angular_005 --> det_AngularLazyRouteDetector
det_AngularNoAnyDetector["Angular No<br/>Any"]
angular_002 --> det_AngularNoAnyDetector
det_AngularOnPushDetector["Angular On<br/>Push"]
angular_001 --> det_AngularOnPushDetector
det_AngularSelectorPrefixDetector["Angular Selector<br/>Prefix"]
angular_004 --> det_AngularSelectorPrefixDetector
det_AngularSubscriptionLifecycleDetector["Angular Subscription<br/>Lifecycle"]
angular_003 --> det_AngularSubscriptionLifecycleDetector
Detector Class Hierarchy
%%{init: {"theme": "base"}}%%
classDiagram
    direction TB
    class ViolationDetector {
        <<abstract>>
        +detect(context, config)
    }
    class det_01["Angular Lazy Route"]
    ViolationDetector <|-- det_01
    class det_02["Angular No Any"]
    ViolationDetector <|-- det_02
    class det_03["Angular On Push"]
    ViolationDetector <|-- det_03
    class det_04["Angular Selector Prefix"]
    ViolationDetector <|-- det_04
    class det_05["Angular Subscription Lifecycle"]
    ViolationDetector <|-- det_05
Analysis Pipeline
%%{init: {"theme": "base", "flowchart": {"useMaxWidth": false, "htmlLabels": true, "nodeSpacing": 50, "rankSpacing": 70}}}%%
flowchart TD
Source(["Source Code"]) --> Parse["Parse & Tokenize"]
Parse --> Metrics["Compute Metrics"]
Metrics --> Pipeline{"5 Detectors"}
Pipeline --> Collect["Aggregate Violations"]
Collect --> Result(["AnalysisResult<br/>5 principles"])
Analysis States
%%{init: {"theme": "base"}}%%
stateDiagram-v2
    [*] --> Ready
    Ready --> Parsing : analyze(code)
    Parsing --> Computing : AST ready
    Computing --> Detecting : metrics ready
    Detecting --> Reporting : 5 detectors run
    Reporting --> [*] : AnalysisResult
    Parsing --> Reporting : parse error (best-effort)

Configuration

languages:
  angular:
    enabled: true
    pipeline:

See Also

  • TypeScript — Shared frontend type-safety foundations
  • React — Another component-centric UI framework with different trade-offs
  • Configuration — Per-language pipeline overrides