The RxJS filter operator is probably one of the most popular operators. As the name suggests you can filter on values emitted by the source Observable. Because you can pass any predicate returning a boolean, the operator can be used in so many cases.
RxJS filter only passes values if they meet specified criteria
One of the most used functions to demonstrate the filter operator is one that checks for odd and even numbers. In the below case, we have got a stream of numbers and only want the even ones to be part of the output:
const result$ = interval(1).pipe(
take(6),
filter(n => n % 2 === 0),
);
expectObservable(result$).toBe('-a-b-c|', { a: 0, b: 2, c: 4 });
The interval(1)
emits the numbers 0 to 5 because of the take(6)
. Applying a filter
with modulo makes sure only the even numbers pass. The result sequence completes after the source stream has completed.
RxJS filter with BooleanConstructor
There is a variant of the filter
operator that some of us often use without knowing the definition:
filter(predicate: BooleanConstructor): OperatorFunction<T, TruthyTypesOf<T>>
Filter not only accepts a function but also a BooleanConstructor
. This allows us to do the following:
const result$ = of(1, 2, undefined, 3, null, '', 4, 'other string', {}).pipe(
filter(Boolean),
);
expectObservable(result$).toBe(
'(abcdef|)',
{ a: 1, b: 2, c: 3, d: 4, e: 'other string', f: {} }
);
The Boolean
constructor is applied on each input and only forwards values that evaluate to true.
Use RxJS filter to check types
Sometimes we do not want to check the value, but the type of an element coming from the source sequence:
const result$ = of(1, undefined, 2, '', 4, 'other string', {}).pipe(
filter((v: any) => typeof v === 'string'),
);
expectObservable(result$).toBe(
'(ab|)',
{ a: '', b: 'other string' }
);
This has the drawback that the type of result$
is still Observable<any>
but we can fix this by applying a guard (: v is string
):
const result$ = of(1, undefined, 2, '', 4, 'other string', {}).pipe(
filter((v: any): v is string => typeof v === 'string'),
);
expectObservable(result$).toBe(
'(ab|)',
{ a: '', b: 'other string' }
);
Now the result$
is of type Observable<string>
.
Exercise for the RxJS filter operator 💪
Only consider clicks on div elements:
<!DOCTYPE html>
<head>
<script src="../../../node_modules/rxjs/dist/bundles/rxjs.umd.js"></script>
</head>
<body>
<div style="background: red; height: 300px; margin-bottom: 100px; display: block;">div content</div>
<span>span content</span>
<script>
const filter = rxjs.filter;
const fromEvent = rxjs.fromEvent;
const clickEvents$ = fromEvent(window, 'click');
clickEvents$.pipe(
).subscribe({
next: (e) => console.log(e)
});
</script>
</body>
As always the code examples can be found on GitHub.