In an Angular 22 project, what does the strictTemplates compiler option check, and where is it configured?
answer
- TypeScript rules applied to templates
- lives in angularCompilerOptions
- bindings assigned to input types
- default flipped in a recent major
basics
~20 sstrictTemplates, set in angularCompilerOptions in tsconfig and on by default since Angular 22, makes the compiler type-check templates like TypeScript code: bindings against input types under strictNullChecks, typed $event and local references, and expressions inside embedded views.
solid answer
~50 s`strictTemplates` lives in the `angularCompilerOptions` block of `tsconfig.json`. The compiler turns every template into a **type-check block**, a TypeScript function that mirrors the bindings, and asks TypeScript for errors, which are reported at the template location. With strict mode on, the compiler checks that each binding is assignable to the input it targets (honouring `strictNullChecks`), infers `$event` for outputs and DOM events, types `#ref` local references by element or directive, infers generic directive types and template contexts, and checks inside embedded views. It also gates Angular's extended diagnostics, which only run in strict mode. Since **Angular 22** it defaults to `true`; `ng update` writes `"strictTemplates": false` into tsconfigs that never set it, so upgraded projects keep their old behaviour until they opt in. Host bindings are checked separately by `typeCheckHostBindings`, on by default since v21.
go deeper
Remember where the option lives, that it makes templates type-checked like TypeScript, and that it is on by default in Angular 22.
Explain type-check blocks and list the concrete checks strict mode adds: input assignability with null safety, $event types, local ref types and generic inference.
Plan the rollout on an upgraded codebase: remove the migration's explicit false, triage errors into real bugs versus typing gaps, and pick the narrowest escape hatch for each.
Treat strict templates as a policy decision across teams: the cost of a one-time error backlog against catching binding bugs at build time for every future change.
## Why templates need their own type checking An Angular template is not TypeScript, so `tsc` alone never sees a mistake such as binding a string to a numeric input or reading a property that does not exist. The Angular compiler closes that gap. For every component it generates a **type-check block (TCB)**: a TypeScript function that is never emitted or executed, but which expresses the template's bindings, variables and directive inputs as ordinary TypeScript statements. TypeScript checks the TCB, and the compiler maps any error back to the line and column in the template. ## Strict versus basic checking | Mode | How it is selected in Angular 22.2 | What it checks | | :-- | :-- | :-- | | Basic | `strictTemplates: false` | Top-level expressions only; embedded views are skipped and pipes, `$event` and `#refs` are mostly `any` | | Strict | `strictTemplates: true`, or unset | Embedded views, pipe return types, and the checks below | Older guides describe a middle **full** mode selected by `fullTemplateTypeCheck`. That flag was deprecated in Angular 13, and the 22.2 compiler no longer reads it: turning `strictTemplates` off drops straight to basic checking, unless individual strictness flags are switched back on. ## What strict mode adds - **Input assignability**: `[count]="expr"` must be assignable to the `count` input's type, for both `input()` and `@Input()`. - **Null safety**: those assignments obey TypeScript's `strictNullChecks`, so `User | null` is not accepted by an input typed `User`. - **Generic inference**: generic components and directives get their type parameters inferred from bindings. - **Template context types**: directives that declare a context type (such as `NgFor`) give `let-` variables real types. - **`$event` types** for component outputs, animation events and DOM events. - **Local reference types**: `<input #box>` makes `box` an `HTMLInputElement`, not `any`. - **Extended diagnostics**: the `NG81xx` family of warnings only emits when strict mode is enabled. ## Where it is configured The option sits beside TypeScript's own settings, in the `angularCompilerOptions` block: ```json { "compilerOptions": { "strict": true }, "angularCompilerOptions": { "strictTemplates": true, "strictInjectionParameters": true, "strictInputAccessModifiers": true } } ``` It is a compiler option, not an `angular.json` builder option, so `ng build`, `ng serve`, the test builders and the Language Service in an editor all apply the same setting. ## How the defaults moved 1. **Angular 13** deprecated `fullTemplateTypeCheck` in favour of the `strictTemplates` family; the 22.2 compiler no longer reads it. 2. **Angular 21** turned on `typeCheckHostBindings` by default, so expressions in a component's `host` object and in `@HostBinding` / `@HostListener` are type-checked too. 3. **Angular 22** made `strictTemplates` default to `true` when a tsconfig does not set it. The `ng update` migration for v22 adds `"strictTemplates": false` to project tsconfigs that did not set it, preserving the old behaviour; a new project created with `--strict false` also writes `false`. The consequence for interviews: "strict templates are opt-in" was true for years and is stale for new Angular 22 projects, while an upgraded project may still carry an explicit `false`. ## What strict mode cannot do - It checks **types at build time**, not data at runtime: an HTTP response that does not match its interface still passes. - It only knows what the types say. If a library's typings omit `null`, or `$event.target` is typed as the generic `EventTarget`, strict mode reports errors that are really typing gaps. - For those cases Angular offers escape hatches of increasing breadth: a non-null assertion (`value!`), the `$any()` cast, an individual strictness flag such as `strictNullInputTypes: false`, and finally `strictTemplates: false`, which falls back to basic checking. ## How errors are reported - For an inline `template`, the error names a **synthetic file** such as `user-page.ts.UserPage.html`, which the compiler never writes to disk; line and column are relative to the template string. - For a `templateUrl`, the error points into the real `.html` file. - The location is the attribute or text node containing the faulty expression, so `[user]="selected()"` is reported at that attribute. - The same diagnostics appear in `ng build`, in `ng serve` rebuilds, and in the editor through the Language Service, so a team sees them before committing. ## Interview framing A strong answer names the location (`angularCompilerOptions`), the mechanism (type-check blocks checked by TypeScript), two or three concrete checks (input assignability with null safety, `$event`, local refs), and the current default with its version.
- Why might an Angular project upgraded to v22 still have strict template checking off?The v22 `ng update` migration adds `"strictTemplates": false` to every project tsconfig that never set the option, so the upgrade does not suddenly break the build with new template errors. The team has to remove that line, or set it to `true`, to adopt the new default.
- Are expressions in an Angular component's host bindings covered by strictTemplates?They are governed by a separate option, `typeCheckHostBindings`, which defaults to `true` since Angular 21. It type-checks the `host` object literal and `@HostBinding` / `@HostListener` expressions. Upgraded projects that hit previously hidden errors there can fix them or set the option to `false`.
saying these in an interview costs you the question
- strictTemplates is an angular.json build option that only affects production builds.
- Strict template checking is always opt-in and off unless ng new --strict was used.
- With strict templates on, the compiler also validates HTTP response data at runtime.
- Template type errors are only visible in the browser console after the page loads.
- strictTemplates and fullTemplateTypeCheck must both be set to true to get strict mode.