'Filter undefined from RxJS Observable

Is there a specific idiom or utility used to filter undefined from RxJS observables? This code has the behavior I want:

obs.pipe(filter(x => x !== undefined))

Some alternatives are

obs.pipe(filter(x => x)) // for all falsy values

obs.pipe(filter(Boolean)) // for falsy variables using Boolean ctor


Solution 1:[1]

Strictly speaking, using filter alone to remove undefined values doesn't do everything that you need. It filters out the undefined values, but does not change the type to indicate that undefined is no longer a possible value.

In the example:

const obs = new Subject<string | undefined>;
const stringObs = obs.pipe(filter(x => x !== undefined))

the stringObs observable still has the type Observable<string | undefined>.

To get round this problem, you need to use:

const stringObs = obs.pipe(filter(x => x !== undefined) as OperatorFunction<string | undefined, string>)

This is only really an issue if you use strict null checks, but if you do (and arguably you should) then creating a custom operator suddenly makes a lot more sense! Something like

function filterNullish<T>(): UnaryFunction<Observable<T | null | undefined>, Observable<T>> {
  return pipe(
    filter(x => x != null) as OperatorFunction<T | null |  undefined, T>
  );
}

does the job.

You can then use:

const stringObs = obs.pipe(filterNullish())

and the type of stringObs will be Observable<string>. I was quite impressed that Typescript manages to infer the type of T correctly.

Solution 2:[2]

To help typescript understand that undefined values have been removed, one way is to create a custom operator. Another way is possible via a user-defined type guard.

function isDefined<T>(arg: T | null | undefined): arg is T extends null | undefined ? never : T {
  return arg !== null && arg !== undefined;
}

const obs = from(['hello', null, undefined]);
const filtered: Observable<string> = obs.pipe(filter(isDefined));

Solution 3:[3]

Rxjs operators are considered low-level and are intended to be combined in a readable way to create a resultant observable that you can use predictably. Having a 'utility' do that for you isn't exactly what I would (humbly) call "the rxjs way". If by 'idiom' you mean like a convention, your code example is basically what you're looking for.

I myself use that exact filter pattern on a regular basis, to the point where I've considered making a custom operator; however, rather than this:

obs.pipe(filter(x => x !== undefined))

You'll just end up with this:

obs.pipe(notUndefined()) // or hasValue() or whatever you want to name it...

There are not a lot of savings here. I would argue that you're not even getting savings in readability (or a totally marginal one, at that), which is why I've never gotten around to it. Another justification for not mobilizing on that is that it is also common to filter against a boolean value, which then starts to make you wonder if you should combine the two to avoid having too many confusing/like operators, all of which could be easily created using filter anyways, etc etc...

Long story short, I've thought about this exact issue a lot, and would argue that you simply use the code example you provided. It's "correct". It's "rx-js-y". It's readable.

Solution 4:[4]

I think i'm right in saying you can just use:

obs.pipe(filter(x => x))

which is equal too:

obs.pipe(filter(x => x !== null && x !== undefined))

Solution 5:[5]

As the latest version of the typescript expects a predicate of boolean, it is not supporting previous falsy filters like:

filter(x => x)

in that case you might want to use:

filter(x => !!x)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Simon Williams
Solution 2
Solution 3 dudewad
Solution 4 Chris
Solution 5 Syed Mohammad Fahim Abrar