Master Angular signals vocabulary — reactive primitives, computed values, effects with cleanup, and zoneless apps.
0 / 5 completed
1 / 5
During standup, the team is adopting Angular signal(). How does it work?
signal(initialValue) returns a getter function — calling mySignal() reads the value and, inside a computed() or effect(), registers a dependency. .set(newValue) replaces the value; .update(fn) derives the new value from the current one. Any computed or effect that read the signal is automatically re-evaluated.
2 / 5
In a PR review, a colleague uses computed() for an expensive calculation. What should they know about it?
computed() is lazy and memoised — it doesn't run until first read, and then caches the result. It only re-executes when one of the signals read inside it (e.g. a() or b()) changes. Subsequent reads before any dependency changes return the cached value, making it efficient for expensive derivations.
3 / 5
An incident reveals memory leaks caused by effect() not cleaning up. How do you add cleanup?
Inside an effect(), return a cleanup function to handle teardown. Angular calls this function before the effect re-runs (when dependencies change) and when the component or injection context is destroyed. This is the correct pattern for cancelling timers, unsubscribing, or aborting fetch requests started inside an effect.
4 / 5
In a design review, the team considers provideExperimentalZonelessChangeDetection. What does it do?
provideExperimentalZonelessChangeDetection() removes the Zone.js dependency that Angular traditionally used to detect async operations. In a zoneless app, change detection is triggered only by signal writes and explicit ChangeDetectorRef.markForCheck() calls — reducing overhead and eliminating Zone.js's bundle cost (~10KB gzipped).
5 / 5
During a code review, a teammate adds toSignal() to bridge RxJS and Angular signals. What does it do?
toSignal(observable$) subscribes to the Observable and exposes its latest emitted value as a signal. It automatically unsubscribes when the injection context is destroyed. Provide { initialValue: defaultVal } to avoid the synchronous undefined on first read. This is the standard bridge when migrating from RxJS-heavy codebases to signals.