Compiler Improvements
Angular 22's compiler brings better type narrowing with ?., correct undefined semantics for optional chaining, HTML comment support, and data-* attribute isolation.
1. Safe Navigation + Type Narrowing
The ?. operator now correctly narrows nullable types in templates. The compiler understands that after user()?.company succeeds, company is non-null in the rest of the expression.
Alicealice@example.comAngular Inc.Reactville9021095Narrowed! After @if (user(); as u), u is UserProfile (not null):
Alice works at Angular Inc. in Reactville
// Deep safe navigation with narrowing
{{ user()?.company?.address?.city ?? 'undefined' }}
// Narrowing: u is UserProfile (not null)
@if (user(); as u) {
{{ u.name }} // no ?. needed, type is narrowed
@if (u.company; as co) {
{{ co.name }} // co is Company, not undefined
}
}2. Optional Chaining Returns undefined
Previously, Angular's ?. could return null in some cases. Now it always returns undefined when the chain short-circuits , matching standard JavaScript behavior.
#6366f1 string (nullish) undefined ✓ (nullish) undefined ✓ // Angular 22: ?. returns undefined (not null)
{{ config().features?.darkMode }}
// result: undefined (not null) when features is missing
@if (config().features?.darkMode !== undefined) {
Dark mode is {{ config().features?.darkMode }}
}3. HTML Comments in Templates
Angular 22 now preserves standard HTML comments in templates. Previously, <!-- ... --> was stripped. Now you can use them for documentation, conditional markers, or third-party integrations that read DOM comments.
<!-- These comments are preserved in the rendered DOM -->
<!-- Angular 22: HTML comments supported in templates -->
<div>
<!-- Section: user-visible content -->
<p>Content here</p>
<!-- End section -->
</div>4. data-* Attributes Are Isolated
data- prefixed attributes no longer accidentally bind to component inputs or outputs. They're treated as plain HTML data attributes , useful for testing IDs, analytics hooks, and CSS selectors.
Inspect the badges above in DevTools:
data-tag-idanddata-testidare plain HTML attributes (not bound to inputs)[label]and[color]are the actual Angular input bindings- In Angular <22, writing
data-label="x"on a component with alabelinput could accidentally bind it
<!-- data-* attributes stay as HTML attributes -->
<app-tag-badge
[label]="tag.label" <!-- Angular input binding -->
[color]="tag.color" <!-- Angular input binding -->
[attr.data-tag-id]="tag.id" <!-- plain data attribute -->
data-testid="tag-badge" <!-- plain data attribute -->
/>
<!-- data-label will NOT bind to the label input anymore -->Summary
- Safe navigation narrowing ,
?.correctly narrows nullable types through the chain. Afteruser?.companysucceeds,companyis non-null. - Optional chaining =
undefined, Short-circuited?.returnsundefined, notnull, matching JavaScript semantics. - HTML comments ,
<!-- ... -->in templates are preserved in the rendered DOM instead of being stripped. data-*isolation ,data-prefixed attributes are treated as plain HTML attributes and never bind to component inputs or outputs.
Inspect this element in DevTools , you'll see HTML comments in the DOM.
This paragraph has a comment above and below it in the template source.