Graceful Deprecations: Bridging Signal Inputs In short: Signal inputs are read-only, so the old setter trick does not work. Keep both inputs, resolve them with a , and warn once through the input's function. Deleting an input and letting twenty teams discover it at build time is not a migration strategy. Teams that get burned once develop upgrade anxiety, stop bumping versions, and end up eleven releases behind — which is where Chapter 4's copy-paste failure starts. A deprecation is a promise with a date on it: this still works, here is what replaces it, here is when it goes. Why the old pattern does not apply In decorator-era Angular, the bridge was a setter: Neither half of that works now. returns a read-only signal — there is no setter to intercept, and does not compile. Writing to your own input was the anti-pattern Chapter 1 warned about anyway. The signal-input bridge Keep both inputs, resolve with a , and warn in the deprecated input's . First a small helper, once, in the library: Then the component: Four properties worth noting: Warns once per component type , not once per instance. A grid of 200 cards logs one line, not 200 — which is the difference between a useful warning and noise people filter out. Development only. keeps it out of consumers' production consoles. Names the fix , including the exact command to run. A warning that does not say what to do instead is just an alarm. New wins. A consumer migrating one binding at a time gets predictable behaviour. The JSDoc half The console warning catches templates that render. The JSDoc tag catches the developer before they run anything: Editors strike through deprecated symbols and show the message on hover. A bare with no replacement is close to useless — always include what to use, why, and when it goes. You can also make it fail a consumer's build if they choose: Deprecating a CSS custom property Chapter 6 made tokens API, so they need the same treatment. There is no console warning available, but there is a bridge: Consumers still setting the old name keep working, and consumers reading it get the new value. Add it to the deprecations section of the release notes, since the compiler cannot help here. A useful trick: a Stylelint rule in the consumer's config that flags the old name, published as part of your migration guide. The lifecycle Three stages, with dates attached: Version State What happens --- --- --- 11.4.0 (minor) Deprecated Both inputs work. JSDoc strike-through, one dev warning. Announced in the release notes. 11.4 → 12.0 Migration window 3–6 months. Both work. migration published early so teams can migrate on their own schedule. 12.0.0 (major) Removed deleted. The Chapter 8 API diff flags it as breaking; the label plus a schematic clears it. Two rules that make this credible rather than theatrical: Publish the migration schematic at deprecation time, not at removal time. If teams can run the day the deprecation lands, most of them will, and by the time 12.0 arrives the removal is uneventful. Holding the schematic back until the major release compresses everyone's work into the same week. Verify before you delete. Chapter 8's tooling can be pointed at consumer repositories to count usages. Deleting something with fourteen live usages is not a deprecation, it is a breaking change with extra steps. What cannot be bridged Not everything has a compatibility path, and it is better to say so than to pretend: Change Bridgeable? --- --- Renamed input Yes — both inputs, resolve Renamed CSS custom property Yes — old aliases to new Renamed component selector Yes — a deprecated directive with the old selector Output payload shape changed Partly — emit a new output, deprecate the old Component removed entirely No — schematic plus a migration note Accessible behaviour changed No — announce it loudly; it is behaviour, not shape Footprint changed No — see the versioning table For the unbridgeable ones the answer is a longer notice period and a better migration guide, not a cleverer bridge. "But I thought deprecation warnings were noise nobody reads" This is a fair conclusion from experience. Most console warnings are noise. Anyone who has opened a browser console in a large application has seen forty of them scroll past and learned to ignore the whole channel. The reason is usually the warning's design rather than the concept, and there are four specific ways they go wrong: They repeat. A naive implementation warns per render. Two hundred cards on screen produces two hundred identical lines, which buries everything else and trains people to filter the channel. The set above fixes this. They reach production. Warnings in a consumer's production console are pure noise to their users' devtools and get muted at the logger. fixes this. They do not say what to do. "statusText is deprecated" leaves the developer to search for the replacement. Naming the new input and the exact command converts a nuisance into a task. They arrive alone. A console warning…