Platform: Typescript 2.4.2 causing is not assignable to type 'Action'

Created on 10 Aug 2017  路  2Comments  路  Source: ngrx/platform

I'm submitting a...


[X] Regression (a behavior that used to work and stopped working in a new release)
[ ] Bug report  
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Version of affected browser(s),operating system(s), npm, node and ngrx:

with [email protected] i can do ng build --prod sadly it breaks with [email protected]

Other information:

ERROR in /Users/ricardo_varanda/Projects/xxx/src/app/modules/auth/auth.effects.ts (15,2): Type 'Observa
ble<LoginFailAction | Observable<LoginSuccessAction>>' is not assignable to type 'Observable<Action>'.
  Type 'LoginFailAction | Observable<LoginSuccessAction>' is not assignable to type 'Action'.
    Type 'Observable<LoginSuccessAction>' is not assignable to type 'Action'.
      Property 'type' is missing in type 'Observable<LoginSuccessAction>'.
ERROR in /Users/ricardo_varanda/Projects/xxx/src/app/modules/cms/notifications/effects/notifications-ef
fect.service.ts (28,3): Type 'Observable<{} | NotificationsLoadedAction>' is not assignable to type 'Observable<Ac
tion>'.
  Type '{} | NotificationsLoadedAction' is not assignable to type 'Action'.
    Type '{}' is not assignable to type 'Action'.
ERROR in /Users/ricardo_varanda/Projects/xxx/src/app/modules/cms/notifications/effects/notifications-ef
fect.service.ts (42,3): Type 'Observable<{} | NotificationDeletedAction>' is not assignable to type 'Observable<Ac
tion>'.

Effects

 @Effect() loginAction$: Observable<Action> = this.actions$
   .ofType(LOGIN_ACTION)
   .switchMap((action: any) => this.trainingApi.login(action.payload.username, action.payload.password)
     .map(user => {
       this.router.navigateByUrl(this.authService.getRedirectUrl() || '/home');
       return Observable.of(new LoginSuccessAction(user));
     })
     .catch(error => {
       console.log('ERROR', error);
       return Observable.of(new LoginFailAction(error));
     }));

Actions

export const LOGIN_ACTION = 'LOGIN_ACTION';

export class LoginAction implements Action {
  type = LOGIN_ACTION;

  constructor(public payload: {username, password}) {}

}

Most helpful comment

Hello, you get error because you expect Observable<Action> but you receive Observable<Observable<Action>>

 @Effect() loginAction$: Observable<Action> = this.actions$
   .ofType(LOGIN_ACTION) 
   .switchMap((action: any) => this.trainingApi.login(action.payload.username, action.payload.password)
     .map(user => {
       this.router.navigateByUrl(this.authService.getRedirectUrl() || '/home');
       return Observable.of(new LoginSuccessAction(user)); // you return Observable.of(...) in map operator. 
     }) 
     .do (action => console.log(action)) // you will get Observable<Action> but expect Action
     .catch(error => {
       console.log('ERROR', error);
       return Observable.of(new LoginFailAction(error));
     }));

Typescript has stricter type checking for generic functions, so now typescript throws errors that were but not found before.

Also returns Promise<boolean>, I think better solution would be

.switchMap((action: any) => this.trainingApi.login(action.payload.username, action.payload.password)
.switchMap(user => (
  Observable.of(this.router.navigateByUrl(this.authService.getRedirectUrl() || '/home').mapTo(user)
))

All 2 comments

Hello, you get error because you expect Observable<Action> but you receive Observable<Observable<Action>>

 @Effect() loginAction$: Observable<Action> = this.actions$
   .ofType(LOGIN_ACTION) 
   .switchMap((action: any) => this.trainingApi.login(action.payload.username, action.payload.password)
     .map(user => {
       this.router.navigateByUrl(this.authService.getRedirectUrl() || '/home');
       return Observable.of(new LoginSuccessAction(user)); // you return Observable.of(...) in map operator. 
     }) 
     .do (action => console.log(action)) // you will get Observable<Action> but expect Action
     .catch(error => {
       console.log('ERROR', error);
       return Observable.of(new LoginFailAction(error));
     }));

Typescript has stricter type checking for generic functions, so now typescript throws errors that were but not found before.

Also returns Promise<boolean>, I think better solution would be

.switchMap((action: any) => this.trainingApi.login(action.payload.username, action.payload.password)
.switchMap(user => (
  Observable.of(this.router.navigateByUrl(this.authService.getRedirectUrl() || '/home').mapTo(user)
))

I had this come up as a result of forgetting to import { of } from 'rxjs/observable/of';

Was this page helpful?
0 / 5 - 0 ratings

Related issues

smorandi picture smorandi  路  3Comments

dmytro-gokun picture dmytro-gokun  路  3Comments

brandonroberts picture brandonroberts  路  3Comments

gperdomor picture gperdomor  路  3Comments

mappedinn picture mappedinn  路  3Comments