linkedSignal(): Dependent Mutable State Synchronization
- Last updated
- Prerequisites:
- Angular signals (signal, computed)
- Understanding of derived vs mutable state
- angular
- signals
- linkedSignal
- state
- synchronization
- reactivity
Read at your depth
The practical view
A computed() is derived and read-only; a signal() is writable but independent. linkedSignal() is both: it derives its value from a source (a signal or computed) AND allows explicit writes — until the source changes, at which point it re-syncs to the source. const selectedId = linkedSignal(() => this.items()[0].id);. Reading selectedId() gives the current selection; selectedId.set(otherId) overrides it locally; when items() changes (source recomputed to a different first id), selectedId automatically resets to the new source value. Use it for 'selection that follows a list, but the user can override until the list changes'.
The same idea in other frameworks
The 'derived state reset' pattern in React (key-based remount or useEffect sync) is the analogue.linkedSignal() — the current topic.Vue's watch + ref reset is the manual analogue; no first-class linked ref.Svelte 5 $derived + manual reset in an effect mirrors the same pattern.Legacy vs modern
Effect-based state reset vs linkedSignal
Syncing mutable state from a source via an effect is error-prone (loops, ordering); linkedSignal makes the re-sync declarative and atomic.
selectedId = signal(''); // ❌ OLD
constructor() {
effect(() => this.selectedId.set(this.items()[0]?.id ?? '')); // ❌ OLD: effect writes signalselectedId = linkedSignal(() => this.items()[0]?.id ?? ''); // ✅ NEWInterview gotchas
Context
This tests whether you understand the derived-vs-mutable distinction and the exact use case linkedSignal fills — interviewers want a precise line between the two primitives.
The mechanical answer
computed() is a pure, derived, read-only value: it recomputes from its dependencies and cannot be written. linkedSignal() is derived AND writable: it initializes from a source computation, but the user can call set()/update() to override the value locally. The override lasts until the source changes, at which point the value re-syncs to the new source output. Use computed() when the value is fully a function of other state (formatted text, filtered lists). Use linkedSignal() when you need a mutable piece of state that should reset to follow a changing source — selections, pagination page, expanded item ids, draft defaults. If you tried to use computed() for these, you could never let the user deviate; if you used a plain signal, you'd need an effect to reset it.
Trap
The naive answer is 'linkedSignal is a writable computed'. It is, but the write semantics matter: a write overrides until the source changes, then re-links. Another trap: assuming every source change resets the value — only source value changes (per equality) trigger re-link, and a manual set suppresses re-sync until the next source change. Candidates who articulate the reset-on-source-change semantics show real understanding.
Context
This probes the design rationale — why linkedSignal exists as a primitive rather than being composed from effect + signal, which is exactly what naive developers would build.
The mechanical answer
The naive pattern is an effect that reads a source and writes a signal: effect(() => sel.set(source())). This has several failure modes: if the effect also reads sel (to avoid overwriting), it creates a circular dependency; if it doesn't, it overwrites any manual user selection whenever the source recomputes. Effects also run asynchronously (microtask), so there's a window where the state is stale, and they re-run on every dependency change, causing redundant writes. linkedSignal bakes the re-sync into the signal primitive: the link is recomputed at read/update time with the correct ordering, the manual-override is respected, and there is no separate effect scheduling or circular dependency risk. This is a case of the framework formalizing a common correct pattern to eliminate the subtle bugs.
Trap
The naive answer is 'an effect doing the same thing is fine'. The effect version has ordering, override-clobbering, and circular-dependency bugs that linkedSignal eliminates. Another trap: thinking linkedSignal still runs an effect internally — the re-link is part of the signal's own computation, not a scheduled effect, so reads are always consistent. Candidates who can explain the anti-pattern and its failure modes demonstrate real senior-level understanding.