Это интересный поток. Размышляя об этом, смещение $ и поиск $ на самом деле представляют собой 2 отдельных потока, но с разной логикой, поэтому их следует объединять в самом конце, а не в начале.
Кроме того, мне кажется, что поиск должен сбросить смещение до 0, и я не вижу этого в текущей логике.
Так вот моя идея:
const offsettedOptions$ = offset$.pipe(
tap(() => loading$.next(true)),
withLatestFrom(search$),
concatMap(([offset, searchterm]) => userService.getUsers(offset, searchterm)),
tap(() => loading$.next(false)),
map(({ data }) =>
data.map((user) => ({
label: user.name,
value: user.id
})),
scan((acc, curr) => [...acc, ...curr])
);
const searchedOptions$ = search$.pipe(
tap(() => loading$.next(true)),
concatMap(searchTerm => userService.getUsers(0, searchterm)),
tap(() => loading$.next(false)),
map(({ data }) =>
data.map((user) => ({
label: user.name,
value: user.id
})),
);
const options$ = merge(offsettedOptions, searchedOptions);
Посмотрите, работает ли это или будет иметь смысл. Возможно, мне не хватает некоторого контекста.