TypeScript and Strict Typing Requirements
Compiler Configuration
Every library must extend a shared base configuration that enforces strict type‑checking. The library‑level tsconfig.lib.json must enable at least the following compiler options, either directly or via the base config:
The strict flag must remain true; disabling individual strict‑mode sub‑options is not allowed. Any deviation (e.g., temporarily relaxing a rule during an emergency fix) requires an explicit comment in the pull request and must be tracked for removal.
General Coding Standards
Leverage
readonlyfor properties that are not meant to be mutated after construction, especially in public API models and configuration objects.Use
as constfor literal values and discriminated unions where the exact shape should be preserved.Type guards and assertion functions are encouraged to encapsulate runtime checks and provide compile‑time safety.
Component Typing and Signals
Angular components must be strictly typed, with a strong preference for the signal‑based API introduced in Angular 16+ for inputs, outputs, and model bindings. Signals improve change detection, enable better type inference, and align with the framework’s future direction.
Required: input() and output() signals
Input properties must be declared using the
input()function (from@angular/core), providing a default value and an explicit type:
Output properties must be declared using the
output()function:readonly filterChanged = output<FilterChangeEvent>();Two‑way binding uses the
model()function:readonly searchTerm = model<string>('');
Exceptions to the Signal Requirement
The traditional @Input() and @Output() decorators are allowed only when:
The library must support Angular versions older than 17 where the signal API is unavailable (only if the library explicitly targets those versions).
Interaction with a third‑party library that depends on class property decorators or
set/getpairs cannot be migrated.The component is part of a legacy code path that has a concrete plan for migration and the exception has been approved by the team lead.
Any such exception must be documented in the pull request description with a clear technical justification. A comment must also appear in the source code above the decorated property, referencing the issue or reason.
Component and Directive Typing Rules
All inputs, outputs, and query results (
viewChild,contentChild) must be explicitly typed. Use generic type parameters:readonly filterInputEl = viewChild<ElementRef<HTMLInputElement>>('filterInput'); readonly chipComponents = contentChildren<FilterChipComponent>(FilterChipComponent);The
@Componentand@Directivedecorators must includestandalone: truefor all new components and directives. Libraries should avoid adding to anNgModuleunless backward compatibility requires it.Public methods exposed on components for template or parent interaction must have explicit return types and parameter types; avoid relying on inference for the public API surface.
Service and Utility Typing
Services, facades, and utilities must export typed interfaces for their configuration and result shapes. Use
interfaceovertypefor public contracts unless union or intersection traits maketypemore appropriate.Dependency injection tokens should be typed using
InjectionToken<T>with a clearT:export const FILTER_CONFIG = new InjectionToken<FilterConfig>('FILTER_CONFIG');Return types of all public service methods must be explicitly annotated. Generic methods should be constrained appropriately (
<T extends SomeType>).
Model and Data Shape Definitions
All data shapes shared between components or exposed from
public-api.tsmust be defined as standalone interfaces, enums, or readonly types in dedicated*.models.tsor*.types.tsfiles.Prefer
interfacefor objects; useenumonly when a set of known constants with reverse mapping is needed (numeric enum) or string union withas constwhen the mapping is not required.Complex union types should be expressed as discriminated unions with a literal
kindortypeproperty, enabling exhaustive checking in switch statements.
Linting and CI Enforcement
The ESLint configuration must include
@typescript-eslint/no-explicit-anyset toerror, along with rules that prevent unsafe casting (@typescript-eslint/consistent-type-assertions).A separate rule must warn when traditional
@Input()/@Output()decorators are used without an accompanying justification comment; this can be implemented via a custom ESLint rule or at minimum a code‑review checklist.The CI pipeline runs the TypeScript compiler with
--noEmit(orng lintincluding type‑check) and must block any merge when strict mode errors are present.
All source code must compile without errors or warnings under the strictest settings. Suppressing TypeScript errors with // @ts-ignore or // @ts-expect-error is acceptable only when accompanied by a comment explaining the necessity and only in the narrow scope described in 3.2.