Angular 22

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.

Name:Alice
Email:alice@example.com
Company:Angular Inc.
City:Reactville
ZIP:90210
First score:95

Narrowed! 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.

theme?.primary:#6366f1 string
theme?.font:(nullish) undefined ✓
features?.darkMode:(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.

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.

<!-- 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.

Angular Signals Compiler

Inspect the badges above in DevTools:

  • data-tag-id and data-testid are 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 a label input 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. After user?.company succeeds, company is non-null.
  • Optional chaining = undefined , Short-circuited ?. returns undefined, not null, 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.