Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

defer() no longer allows the observable return type

Today I did an upgrade from angular 6 to 7

Along with it I had to upgrade rxjs from 6.1.0 to 6.3.3 and typescript from 2.7.2 to 3.1.1

And now this ngrx effects method is throwing a typescript error:

  @Effect()
  init$ = defer(() => {
    const userData = localStorage.getItem('user');
    return (userData)
      ? of(new Login(JSON.parse(userData)))
      : of(new Logout());
  });

Argument of type '() => Observable | Observable' is not assignable to parameter of type '() => void | Subscribable | Subscribable | PromiseLike | InteropObservable'.

It seems that I can no longer use defer to dispatch an action like this, so I'm not sure how I can write initialization effects moving forward.

I just need to wait for the store to be initialized, so in this method I am deferring the execution until the effects have subscribed to the actions stream.

Does anyone know how I can work around this?

UPDATE:

I also found a Stackblitz example that leverages ROOT_EFFECTS_INIT, but due to the fact that I am in a feature module, this doesn't work (discussed here)

import { ROOT_EFFECTS_INIT } from '@ngrx/effects';

@Effect()
  init$ = this.actions$
    .ofType(ROOT_EFFECTS_INIT)
    .pipe(
      map(() => {
        const userData = localStorage.getItem('user');
        return (userData)
          ? of(new Login(JSON.parse(userData)))
          : of(new Logout())
      })
    );
like image 598
Nate May Avatar asked Jan 02 '23 17:01

Nate May


1 Answers

This is a TypeScript limitation. You can work around the problem by explicitly specifying the return type in the arrow function:

@Effect()
init$ = defer((): Observable<Action> => { // HERE
  const userData = localStorage.getItem('user');
  return (userData)
    ? of(new Login(JSON.parse(userData)))
    : of(new Logout());
});

Or, more specifically:

@Effect()
init$ = defer((): Observable<Login | Logout> => { // HERE
  const userData = localStorage.getItem('user');
  return (userData)
    ? of(new Login(JSON.parse(userData)))
    : of(new Logout());
});

The problem is that without the explicit return type, the return type of the arrow function is inferred to be:

Observable<Login> | Observable<Logout>

rather than:

Observable<Login | Logout>

Interestingly, although it is indeed a TypeScript limitation, this RxJS PR will solve the problem and will see the correct type inferred.

like image 130
cartant Avatar answered Feb 16 '23 00:02

cartant