Skip to main content

Migrating from RxJS

Migrating from rxjs to @lirx/core is a great choice if you aim to improve globally your applications:

⚡ it strongly improves the performances and reduce the overall size.

📑 it comes with a clear documentation, including direct references to the rxjs's equivalent if one exists. In consequence, you'll never get lost.

🪄 it's simpler by design, and the power of Observable sending data instead of states (no comeplete or error to manage), reduces the complexity of some elaborated pipes or aggregators like switchMap, mergeAll, etc...

Using exclusively @lirx/core in replacement of rxjs is therefore good option, especially in new applications.

For already existing applications, we recommend to slowly replace your old rxjs's Observables with the @lirx/core's ones.

This documentation is here to help you in this migration 🏗️


To convert from the rxjs's Observables to the @lirx/core's one you can use the bridge.


npm install @lirx/rxjs-bridge --save

The installation requires rxjs as a peer dependency.


I guess they speak for themselves.


  • rxjs uses classes, where @lirx/core uses functions. So the class Observable becomes the type IObservable (a function definition). The same is true for Observer => IObserver.
  • rxjs regroups under the same name (Operator), the functions that generate an Observable, and the pipes that chains them (called Pipeable Operator). @lirx/core has a specific type for the pipes: IObservablePipe.

Moreover, @lirx/core tries to be more consistent in its naming:

  • functions are explicit about what they return. For example, if a function returns an IObservablePipe, then it will end with ObservablePipe.
  • it follows the Observable naming convention: a $ is present at the end of a variable name representing an Observable (ex: const value$ = of(5);), and it extends this rule with $$ for a function that generates an Observable, and $$$ for a function that generates an ObservablePipe.

Creating an Observable

Most functions that create an Observable in rxjs have a similar name in @lirx/core. Example:

However, a few may diverge, in their arguments, naming, or internal logic (especially when working with notifications).

Creating an ObservablePipe

The same is true for the Observable pipes:

Subscription / Unsubscription

To subscribe with rxjs, we have to call the subscribe method, which returns a Subscription. Later we can unsubscribe it, using the method unsubscribe:

const subscription = of(1, 2, 3)
.subscribe((value: number) => {


With @lirx/core we just have to call a function, and next call its return:

const unsubscribe = of(1, 2, 3)
((value: number) => {


This simple trick allows @lirx/core to heavily optimize function calls and code.


With rxjs we pipe our Observables with the method pipe:

const subscription = of(1, 2, 3)

With @lirx/core, instead of using a method, we'll use the function pipe$$;

const subscription = pipe$$(of(1, 2, 3), [

If we only have one pipe, we can even inline it:

const subscription = map$$(of(1, 2, 3), String);

It will improve the performances and bundle size.

State of the Observable - next, complete and error

The @lirx/core Observables don't have a complete nor error state. Instead, they just send values defined by their type.

This is somehow, like if they were only sending next. To send a state, we have to use some Notifications.

Subject, BehaviorSubject and ReplaySubject

They are replaced by Sources: