Skip to the solution
HardFrontend9 min read

What are Angular Signals?

384 views

The problem

Question presented to candidate: "Explain Angular Signals to a developer who has only used plain class fields and RxJS. What are signal, computed and effect, and why did Angular add them?"

What a strong answer should cover:

  • A signal is a wrapper around a value that tracks its readers; read by calling it, write with set or update.
  • computed() is a derived, lazy, memoised signal that re-runs only when a dependency it actually read changes.
  • effect() runs side effects when signals it read change; it is for syncing with the outside world, not for deriving state.
  • Equality: setting an equal value notifies nobody; mutating an object in place is invisible; custom equal is possible.
  • untracked() reads without creating a dependency; writing a signal inside computed is an error (NG0600).
  • Why: fine-grained change detection without Zone.js, which is why v22 apps are zoneless and OnPush by default.
  • History: developer preview in v16, signal/computed stable in v17, effect stable in v20.

Clarifying questions expected:

  • "Should I compare them with RxJS as well, or focus on the signal APIs?"

Code / implementation expected: Optional β€” a small component with a signal, a computed and an effect.

  • signals
  • reactivity

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

9 min read Β· 10 sections

Read the code

Angularsignal, computed, effect and untracked in one component
import { Component, computed, effect, signal, untracked } from "@angular/core";

@Component({
  selector: "app-root",
  template: `
    <p>{{ qty() }} x {{ price() }} = {{ total() }} {{ currency() }}</p>
    <button (click)="qty.update(n => n + 1)">Add one</button>
    <button (click)="qty.set(qty())">Set same qty</button>
    <button (click)="currency.set(currency() === 'EUR' ? 'GBP' : 'EUR')">Switch currency</button>
  `,
})
export class AppComponent {
  // 1. signal(): a writable value that remembers who reads it.
  qty = signal(1);
  price = signal(4);
  currency = signal("EUR");

  // 2. computed(): derived, lazy and cached. Depends on qty and price only.
  total = computed(() => {
    console.log("  computed total");
    return this.qty() * this.price();
  });

  constructor() {
    // 3. effect(): a side effect that re-runs when a signal it read changes.
    //    currency is read inside untracked(), so switching it does NOT re-run this.
    effect(() => {
      const t = this.total();
      const cur = untracked(() => this.currency());
      console.log(`  effect: total is now ${t} ${cur}`);
    });
  }
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 109 of 121 in Angular

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Angular questions
Up nextHard

What is the difference between Subject, BehaviorSubject, and ReplaySubject?

Continue