1

I'm trying to use combineLatest, in particular I need to combine four Observables that emit values of different types with a projection function that returns a boolean type.

From what I get from the Rxjs documentation here, I think that this is the combineLatest signature I need to use, which is not deprecated:

combineLatest(sources: readonly any[], resultSelector: (...values: A) => R): Observable<R>

with R being boolean in my case.

Here is my code snippet where I try to use that function, but Visual Studio Code shows the call with strikeout style and it suggests it's deprecated.

this.canBook$ = combineLatest(
                    this.userSvc.canRedirect(this.fbSvc.getUserId()),
                    this.userSvc.canBook(this.fbSvc.getUserId()),
                    this.calSvc.segnaleOrarioIso8601(),
                    this.selectedDay$,
                    (canredir: boolean, canbook: boolean, iso8601: string, selday: ICGiorno) => {
                      return canredir && (dayjs(selday.iso8601).diff(iso8601, 'hour') > 0) || 
                             canbook && (dayjs(selday.iso8601).diff(iso8601, 'hour') >= 24); 
                    } );

VS Code says:

The signature '(v1: Observable<boolean>, v2: Observable<boolean>, v3: Observable<string>, v4: Subject<ICGiorno>, resultSelector: (v1: boolean, v2: boolean, v3: string, v4: ICGiorno) => boolean, scheduler?: SchedulerLike): Observable<...>' of 'combineLatest' is deprecated.ts(6387)

However I'm not passing in any scheduler parameter, so I don't understand why VS Code is matching my call with the deprecated signature instead of the one documented above in the Rxjs API doc.

Can you please help me understand why?

Lucio Crusca
  • 1,277
  • 3
  • 15
  • 41
  • Are you using rxjs v6? It looks like the resultSelector was slated to be deprecated ([`combineLatest@6.67`](https://github.com/ReactiveX/rxjs/blob/6.6.7/src/internal/observable/combineLatest.ts#L17)), but doesn't seem to be the case in v7: [`combineLatest@latest`](https://github.com/ReactiveX/rxjs/blob/master/src/internal/observable/combineLatest.ts#L29) – BizzyBob Aug 30 '21 at 00:19
  • @BizzyBob Yes, I was using v6, but even updating to v7 didn't make the deprecation warning go away. – Lucio Crusca Aug 30 '21 at 07:42

2 Answers2

3

As mentioned in the comments, the overload you're using is deprecated in RxJS@6.6.7 combineLatest, and there is no overload without scheduler, but instead, there are some overloads with scheduler, which are deprecated, e.g:

/** @deprecated resultSelector no longer supported, pipe to map instead */
export function combineLatest<O1 extends ObservableInput<any>, R>(sources: [O1], resultSelector: (v1: ObservedValueOf<O1>) => R, scheduler?: SchedulerLike): Observable<R>;
/** @deprecated resultSelector no longer supported, pipe to map instead */
export function combineLatest<O extends ObservableInput<any>, R>(sources: O[], resultSelector: (...args: ObservedValueOf<O>[]) => R, scheduler?: SchedulerLike): Observable<R>;

But in RxJS@latest combineLatest you can find the overload you mentioned in your question, and it's not deprecated, but the problem in your code is that you're using another overload than mentioned one, which is deprecated also:

/** @deprecated Pass an array of sources instead. The rest-parameters signature will be removed in v8. Details: https://rxjs.dev/deprecations/array-argument */
export function combineLatest<A extends readonly unknown[], R>(
  ...sourcesAndResultSelector: [...ObservableInputTuple<A>, (...values: A) => R]
): Observable<R>;

So, to fix it you just need to use the overload you mentioned correctly (which is not deprecated in RxJS@latest) like the following:

this.canBook$ = combineLatest(
  [ // <<<< The mentioned overload expects an array not Observables as params.
    this.userSvc.canRedirect(this.fbSvc.getUserId()),
    this.userSvc.canBook(this.fbSvc.getUserId()),
    this.calSvc.segnaleOrarioIso8601(),
    this.selectedDay$,
  ], // <<<<
  (
    canredir: boolean,
    canbook: boolean,
    iso8601: string,
    selday: ICGiorno
  ) => {
    return (
      (canredir && dayjs(selday.iso8601).diff(iso8601, 'hour') > 0) ||
      (canbook && dayjs(selday.iso8601).diff(iso8601, 'hour') >= 24)
    );
  }
);
Amer
  • 6,162
  • 2
  • 8
  • 34
2

I would recommend keeping operators (like functions) simple by letting them do one thing. Regardless of what features may/or may not be deprecated in combineLatest(), you can use it just to combine the observables. After that, you can use a map() operator to return your boolean value.

this.canBook$ = combineLatest([
  this.userSvc.canRedirect(this.fbSvc.getUserId()),
  this.userSvc.canBook(this.fbSvc.getUserId()),
  this.calSvc.segnaleOrarioIso8601(),
  this.selectedDay$,
]).pipe(
  map(
    ([canredir, canbook, iso8601, selday]) =>
      (canredir && dayjs(selday.iso8601).diff(iso8601, "hour") > 0) ||
      (canbook && dayjs(selday.iso8601).diff(iso8601, "hour") >= 24)
  )
);
Joshua McCarthy
  • 1,739
  • 1
  • 9
  • 6
  • Whie this is good advice in general and I'll follow it for sure (btw, thank you), it does not really answer my (updated) question, but it only works around the problem, so I don't feel like I should accept it. – Lucio Crusca Aug 30 '21 at 07:48
  • In your original code, try passing your observables in as a single array instead of as multiple values. `combineLatest([obs1$, obs2$, obs3$...]` This should change the type inference from the one giving you this problematic error. This should work if your on version 7. – Joshua McCarthy Aug 30 '21 at 08:49