NgRX 8效果-类型'Observable <未知>'不能分配给类型'Observable <Action>'

ngf*_*ixl 9 typescript ngrx angular angular8

在使用NgRX 8时,我和我的同事在实现效果时经常会遇到奇怪的错误消息。

类型'Observable <未知>'不可分配给类型'Observable <动作> | ((... args:any [])=> Observable <Action>)'

它与类型问题有关。消息如此具体,真是令人讨厌,它标志着完整的效果。这经常出现,而且确实很难解决。

在此处输入图片说明

我们想知道是否可以做些事情以便快速发现问题,或者我们是否能够以某种方式破坏消息的结构。我不是在这里寻找特定的解决方案,而是在寻找一种“如何快速确定问题出在哪里”的方法。

谢谢和欢呼!

可能性的集合

这是我们到目前为止所做的,也是来自评论和答案的想法。

  • 在大多数情况下,动作可能不是问题
  • switchMap参数的错误解构可能是错误的
  • RxJS运算符之一未导入
  • 服务中的参数和返回值错误可能是原因
  • 服务和操作类型不一致也可能是原因
  • 如果没有帮助,并且您确定没有问题,请执行以下操作:重新加载TypeScript

我们仍然希望有一个技巧来分解错误消息。

And*_*len 11

更新-快速版本 -注释掉createEffect(() =>,修复IDE(VSCode)标记的错误,然后createEffect(() =>重新添加。


较早的答案 - @Effect不需要使用,也不是必需的。

我发现调试的最简单方法是使用@Effect装饰器以版本7的方式编写代码,并使用完成重写createEffect

因此要调试:

  navigateToDashboard$ = createEffect(() =>
    this.actions$.pipe(
      ofType(teamActions.CREATE_SUPERVISOR_GROUP_SUCCESS),
      map((action: teamActions.CreateSupervisorGroupSuccess) => action.payload),
      map((team: Team) => team.TeamID),
      SwitchMap(id => new routerActions.Go({ path: ['/team', id, 'populate'] }))
    )
  )
Run Code Online (Sandbox Code Playgroud)

这将无用的错误写为(添加装饰器,删除createEffect(() =>,删除最后的括号),

@Effect()
navigateToDashboard$ = this.actions$.pipe(
    ofType(teamActions.CREATE_SUPERVISOR_GROUP_SUCCESS),
    map((action: teamActions.CreateSupervisorGroupSuccess) => action.payload),
    map((team: Team) => team.TeamID),
    SwitchMap(id => new routerActions.Go({ path: ['/team', id, 'populate'] }))
)
Run Code Online (Sandbox Code Playgroud)

现在我们得到了错误

Cannot find name 'SwitchMap'
Run Code Online (Sandbox Code Playgroud)

其次是

Type 'Go' is not assignable to type 'ObservableInput<any>'
Run Code Online (Sandbox Code Playgroud)

解决这个问题

@Effect()
navigateToDashboard$ = this.actions$.pipe(
    ofType(teamActions.CREATE_SUPERVISOR_GROUP_SUCCESS),
    map((action: teamActions.CreateSupervisorGroupSuccess) => action.payload),
    map((team: Team) => team.TeamID),
    switchMap(id => of(new routerActions.Go({ path: ['/team', id, 'populate'] })))
)
Run Code Online (Sandbox Code Playgroud)

现在用NgRx 8项重写。不漂亮,但可以。

  • 注释掉`createEffect(()=&gt;`)可以正常工作,非常感谢! (2认同)

小智 9

我遇到了完全相同的问题,就我而言,这是因为错误放置的大括号和缺少导入。

这是我为调试和解决它所做的。

将内部可管道功能拆分为单独的功能。这对我来说是最重要的一步,因为复杂的语法和来自 vscode 的自动完成大括号,有时大括号存在于错误的位置并且不容易找到。这也解决了几乎所有其他问题(缺少导入、不正确的返回类型等),因为要调试的代码要小得多,而且 vscode 会从子函数中突出显示这个单独的错误。

这是我以前的

    performLogin$ = createEffect(() => 
       this.actions$.pipe(
           ofType(performLogin),
           mergeMap(() => this.loginService.performLogin().pipe(
               map(() => loginSuccess())
           )))
    );

Run Code Online (Sandbox Code Playgroud)

把这个改成下面

 performLogin$ = createEffect(() => 
       this.actions$.pipe(
           ofType(performLogin),
           mergeMap(() => this.performLogin()),
           catchError((error ) => { console.log("HELLO"); return EMPTY})
       )
    );

    performLogin() {
        return this.loginService.performLogin()
        .pipe(map(() => loginSuccess()));
    }

Run Code Online (Sandbox Code Playgroud)

我从这种方法中得到的另一个好处是内管上的 catchError 块不会被触发(根据效果示例它应该可以工作)。因此必须将其包含在外部管道块中。这里错误被捕获并按预期工作。但仍在弄清楚为什么它不起作用。

总结一下,登录服务做了以下事情(抛出错误或者返回Observable为true)

//login.service.ts

performLogin() : Observable<boolean> {
        throw "Something went wrong";
        //return of(true);
    }

Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。


api*_*cik 7

在处理此问题并使用官方 ngrx 8 示例的情况下。

loadMovies$ = createEffect(() => this.actions$.pipe(
    ofType('[Movies Page] Load Movies'),
    mergeMap(() => this.moviesService.getAll()
      .pipe(
        map(movies => ({ type: '[Movies API] Movies Loaded Success', payload: movies })),
        catchError(() => EMPTY)
      ))
   )
);
Run Code Online (Sandbox Code Playgroud)

简单快速的解决方案可以放置“任何”类型。

loadMovies$: any = createEffect((): any => this.actions$.pipe(
    ofType('[Movies Page] Load Movies'),
    mergeMap(() => this.moviesService.getAll()
      .pipe(
        map(movies => ({ type: '[Movies API] Movies Loaded Success', payload: movies })),
        catchError(() => EMPTY)
      ))
   )
);
Run Code Online (Sandbox Code Playgroud)

不要忘记 rxjs 操作符的导入,observables。

在处理动作负载 - 道具的情况下,定义动作类型。

ofType<MySuperActions>
Run Code Online (Sandbox Code Playgroud)

或者

ofType<ReturnType<typeof myAction>>
Run Code Online (Sandbox Code Playgroud)