RXJS cómo manejar los valores booleanos u observables <boolean> devueltos en switchmap

Sep 02 2020

Para el contexto, tengo dos guardias en una ruta angular, pero no puedo tenerlos a ambos en la ruta. Se pueden activar debido a los efectos secundarios en uno y al hecho de que todos los guardias son controlados en una ruta independientemente.

Entonces, para solucionar, tengo un guardia que llama a los demás canActivate en un caso determinado:

canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot
    ): Observable<boolean> | Promise<boolean> | boolean {
        return this.service.state$.pipe(
            filter((s) => s.updatedFromServer),
            switchMap((s) => {
                if (/* a condition that means this guard is satisfied */) {
                    return this.otherGuard.canActivate(next, state);
                } else {
                    return false;
                }
            })
        );

El tipo de retorno canActivate del otro guardia también es Observable<boolean> | Promise<boolean> | booleany de manera similar puede devolver un booleano u Observable real.

La queja de error de TS ahora es:

Type 'false | Observable<boolean>' is not assignable to type 'ObservableInput<any>'.
Type 'false' is not assignable to type 'ObservableInput<any>'

Si el otro guardia devuelve solo un Observable y el retorno del mapa de interruptores aquí también se cambia a, of(false)entonces parece estar bien, pero preferiría retener las firmas canActivate donde se puede devolver un booleano resuelto, simplemente no sé cómo hacerlo dentro el contexto de un mapa rxjs.

Respuestas

frido Sep 02 2020 at 16:08

Puede comprobar si el resultado es Observable o Promesa con isObservabley isPromise. Si no, envuelva el valor con of.

import { isObservable } from 'rxjs';
import { isPromise } from 'rxjs/internal-compatibility';

return this.service.state$.pipe(
  filter((s) => s.updatedFromServer),
  switchMap((s) => {
    let result: any;
    if (/* a condition that means this guard is satisfied */) {
      result = this.otherGuard.canActivate(next, state);
    } else {
      result = false;
    }
    return isObservable(result) || isPromise(result) ? result : of(result)
  })
);