Custom graphics generated by MidJounrey AI
Before getting into the heart of the debate, it’s worth noting that anyone can weigh in on proposed Angular changes. The team invites feedback through public discussions on each sub-RFC. This piece centers on sub-RFC 4.
Signals and sub-RFC 4 — the basics
A quick primer on Angular Signals: they represent a new model for reactivity in Angular, one that aims to simplify state management while offering precise control over when components update.
Sub-RFC 4 focuses on how Signals will mesh with RxJS Observables — the current backbone of reactive patterns in Angular. The proposal is a key step toward a smoother coexistence.
Signals and RxJS — finding common ground
For Angular Signals, interoperability with established RxJS code is a core goal. This matters for both existing applications and the wider ecosystem of libraries.
To that end, sub-RFC 4 outlines two new functions—toObservable and toSignal—as a bridge in either direction. Both APIs live in @angular/core/rxjs-interop. Remember, these are still early proposals.
The toSignal function
Turning an RxJS Observable into an Angular Signal is what toSignal does:
const counter: Signal<number> = toSignal(counter$);
Under the hood, this function subscribes to the Observable and refreshes the Signal’s value on every emission. The subscription is set up right away, and handling cleanup is automatic — Angular terminates the subscription when the surrounding context is torn down.
Setting an initial value
For times when the Observable hasn’t produced a value yet, toSignal accepts a fallback value that stands in for the Signal’s initial state:
const secondsObs = interval(5000);
const seconds = toSignal(secondsObs, 0);
effect(() => {
console.log(seconds());
});
Handling errors and completion
A Signal encapsulates a single current value and notifies its readers of changes. Observables, by contrast, emit three separate kinds of notifications: next, error, and complete. When the subscription that toSignal manages receives an error notification, that error surfaces the next time the Signal is read — it’s thrown directly. To intercept this, you have options: apply catchError to the Observable before conversion, or use computed on the Signal side to handle it gracefully.
Signals have no equivalent to an Observable’s completion event — there is no “complete” state built in. Still, you can model completion yourself using a separate Signal, or reach for operators like materialize.
The toObservable function
For the inverse conversion, toObservable accepts an Angular Signal and returns an Observable. Internally, subscribing to that Observable triggers an effect, which reads the Signal and forwards each new value along to the subscriber.
const count: Observable<number> = toObservable(mySignal);
The Observable returned by toObservable streams values asynchronously; the underlying effect is what pushes each new Signal value downstream. If you need that initial value without waiting for the next emission cycle, startWith comes in handy:
const obs$ = toObservable(mySignal).pipe(startWith(mySignal()));
Lifecycle behavior and cleanup
With toObservable, the effect doesn’t begin until a subscriber arrives, and it runs for as long as that subscription is active.
That’s a deliberate contrast to toSignal, where the subscription is tied to the creation context and teardown is handled for you.
If you prefer to bind the lifespan of the Observable to a component, it’s easy enough to wire things up manually:
const myValue$ = toObservable(myValue).pipe(takeUntil(this.destroy$))
Conclusion
The intention behind these APIs is to build a practical bridge between RxJS and Signals. Minimizing disruption for existing codebases is a stated priority, so developers can keep using familiar patterns while adopting Signals gradually.
The core of the debate: Signals and Observables
Where the conversation gets lively is around the sub-RFC 4 proposal — in particular, whether a deeper integration should happen. Specifically, should Angular Signals align with widely recognized standards for interoperability, such as Symbol.asyncIterator and Symbol.observable?
Ben Lesh’s perspective
Ben Lesh sees merit in building Signals so they slot directly into existing Observable chains. His reasoning is that Signals naturally operate over time, which fits the Observable model well. Adopting these common interop points would give Angular Signals broader applicability beyond the framework itself.
Alex Rickabaugh’s counterpoints
On the other side, Alex Rickabaugh acknowledges that the team considered precisely this design, but cites obstacles: Angular Signals have some unique traits and reading them safely in the middle of change propagation is not straightforward.
What’s more, Signals depend on an injection context. That dependency could land as an unexpected burden on developers who use them inside Observable pipelines. Signals aren’t Observables, Alex argues; treating conversions between the two as explicit steps helps keep architecture deliberate and sound.
What the Angular Team Decided
The Angular team has not budged on their decision: neither InteropObservable nor any Subscribable interface will be added to Angular Signals. Even though the framework itself is unchanged for now, the conversation has produced useful takeaways and opened up significant questions about how Signals and Observables will evolve.
Keeping Up with the Discussion
The sub-RFC 4 thread shows just how complex it can be to refine Angular. With the community weighing in on these proposals, ongoing debate is inevitable—and in the end it should lead to a stronger implementation. Following these discussions closely, and jumping in when you have something meaningful to contribute, seems like the right move.
Did You Enjoy the Article?
If so, you may want to check out what I’m doing on Twitter. I’m hosting live Twitter Spaces focused on Angular, featuring GDEs and other industry experts. You can join in live, ask questions, or catch the highlights in short video clips.
Interested? Give me a follow on Twitter @DanielGlejzner — it means a lot. Thanks!





