Issues with Patched Observable Operators

January 12th 2018 ReactiveX TypeScript Ionic 2/3

RxJS used to encourage monkey patching of operators and helper functions onto the Observable object:

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/range';
import 'rxjs/add/operator/map';

let Observable.range(0, 10).map(n => n * 2);

However, this has an unfortunate side effect of making the imported functions and operators available everywhere, although they are only imported in a single file. Removing the import from that file can inadvertently break code elsewhere. This behavior is not constrained only to your code but also to any third party libraries you might be using. For example, I stumbled across it when updating Ionic in my application. Suddenly, one of the tests using ionic-mocks failed with:

Observable.empty is not a function.

The root cause was in ionic-mocks, not in my code. It wasn't easy to determine that.

To make matters worse, there's an even broader import available, bringing in a large set of functions and operators with a single line of code:

import { Observable } from 'rxjs';

let observable = Observable.range(0, 10).map(n => n * 2);

To alleviate this problem, alternative imports in the form of lettable operators are available since RxJS 5.5. Using them requires a change in the syntax:

import { range } from 'rxjs/observable/range';
import { map } from 'rxjs/operators/map';

let observable = range(0, 10).pipe(map(n => n * 2));

But there's a huge benefit: the imported functions and operators are not monkey patched and hence only available in the file where they are imported. This makes sure that all the required imports are added to each individual file, preventing changes in one file from breaking code in other files. Additionally, the new syntax makes it easier to write custom operators and brings other advantages as well. There really is no reason to keep using the old syntax. Let's hope that the libraries we depend on will make the transition soon.

Copyright
Creative Commons License