selectSlice
RxJS operator that emits only the provided keys from the source Observable. Each key is filtered to emit only defined values and checked for distinct emissions; comparison is done for each key in the keys array. A selection is only emitted when it is valid (every selected key must exist and be defined in the source), so the operator always yields a complete slice with all values present.
You can fine-grain the distinct checks by passing a KeyCompareMap for the keys you want to compare explicitly.
Signature
function selectSlice<T extends object, K extends keyof T>(keys: K[], keyCompareMap?: KeyCompareMap<{ [P in K]: T[P] }>): OperatorFunction<T, PickSlice<T, K>>;
The result type is PickSlice<T, K>; there is no | null in the emitted type. Invalid selections are not emitted at all (they are filtered out upstream) rather than surfaced as null.
Parameters
| Parameter | Type | Meaning |
|---|---|---|
keys | K[] | The keys to select from the state object. |
keyCompareMap | KeyCompareMap<{ [P in K]: T[P] }> | Optional. Custom compare functions for specific keys. |
Returns
OperatorFunction<T, PickSlice<T, K>>, an operator that emits distinct, complete slices of the selected keys.
Import
import { selectSlice } from '@rx-angular/state/selections';
Example
import { of, Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { selectSlice, KeyCompareMap } from '@rx-angular/state/selections';
interface MyState {
title: string;
items: string[];
panelOpen: boolean;
}
// custom compare logic for the items array
const customComparison: KeyCompareMap<MyState> = {
items: (oldItems, newItems) => compareItems(oldItems, newItems),
};
const state$: Observable<MyState> = of({ title: 'myTitle', items: ['foo', 'bar'], panelOpen: true }, { title: 'myTitle', items: ['foo', 'bar'], panelOpen: false }, { title: 'nextTitle', items: ['foo', 'baR'], panelOpen: true }, { title: 'nextTitle', items: ['fooRz', 'boo'], panelOpen: false });
state$.pipe(selectSlice(['title', 'items'], customComparison), tap(console.log)).subscribe();
// displays:
// { title: 'myTitle', items: ['foo', 'bar'] }
// { title: 'nextTitle', items: ['foo', 'baR'] }
// { title: 'nextTitle', items: ['fooRz', 'boo'] }
Signal alternative
For reading a slice inside a component, prefer a native computed() over selectSlice + the async pipe; assemble the slice from the individual state.signal(...) reads:
protected readonly slice = computed(() => ({
title: this.title(),
items: this.items(),
}));
Keep selectSlice for RxJS pipelines where you are composing Observable sources before they reach state.
See also
- Concept: Reactive state: global vs local, RxState + signals
- Reference:
select·distinctUntilSomeChanged·stateful