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

时间:2019-07-29 05:25:11

标签: angular typescript ngrx angular8

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

  

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

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

enter image description here

我们想知道是否可以做一些事情来快速发现问题,或者我们是否能够以某种方式破坏消息的信息。

谢谢和欢呼!

11 个答案:

答案 0 :(得分:16)

更新-快速版本-注释掉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'] }))
    )
  )

将无用的错误写为(添加装饰器,删除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'] }))
)

现在我们得到了错误

Cannot find name 'SwitchMap'

之后

Type 'Go' is not assignable to type 'ObservableInput<any>'

修复此问题

@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'] })))
)

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

答案 1 :(得分:4)

我遇到了完全相同的问题,在我的情况下,这是因为括号放置错误和导入丢失所致。

这是我调试和解决问题的方法。

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

这是我以前所拥有的

var myString = "John:31,Miranda:28"
var myObj = myString.split(',').reduce(function (obj, part) {
  var pieces = part.split(':')
  obj[pieces[0]] = pieces[1]
  return obj
}, {})

将此更改为以下

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

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

总结起来,登录服务会执行以下操作(引发错误或返回Observable为true)

 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()));
    }

希望这会有所帮助。

答案 2 :(得分:4)

在处理此问题并使用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)
      ))
   )
);

便捷的解决方案可以放入“任意”类型。

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)
      ))
   )
);

别忘了为rxjs运算符导入可观察的东西。

如果要处理动作有效载荷-道具,请定义动作类型。

ofType<MySuperActions>

ofType<ReturnType<typeof myAction>>

答案 3 :(得分:0)

请确保您是从这样的操作(强类型).ts文件中调用操作的

effectName$ = createEffect(
  () => this.actions$.pipe(
    ofType(FeatureActions.actionOne), // this line
    map(() => FeatureActions.actionTwo())
  )
);

答案 4 :(得分:0)

实际上,您需要将createAction创建的动作视为函数,然后调用它以返回动作对象。选中此desc。因此,您的of(addCommentFailed)应该是of(addCommentFailed())

答案 5 :(得分:0)

我遇到了这个问题,因为这里缺少导入'of'运算符

// events.effects.ts
...

getEvents$: Observable<Action> = createEffect(
    () => this.actions$.pipe(
      ofType(EventsActions.getEvents),
      switchMap(action =>
        this.eventService.getEvents().pipe(
          map(events => EventsActions.getEventsSuccess({ events })),
          catchError(error => of(EventsActions.getEventsError({ error })))
        )
      )
    )
  );
...

我已通过在顶部添加此行代码来修复它

// events.effects.ts

import { Observable, of } from 'rxjs';

...

答案 6 :(得分:0)

我今天遇到了类似的问题(错误消息相同),这是因为TypeScript无法正确推断Array#flatMap的返回类型。我假设Array#mapRxJS#map或任何未明确键入的数组都是相同的。

以下是崩溃的代码:

this.actions$.pipe(
    ofType(ActionType),
    switchMap((action) => {
        return action.cart.flatMap((cartItem: CartItem) => {
            if (x) {
                return [
                    ActionCreator1(params1),
                    ActionCreator2(params2)
                ];
            } else {
                return [];
            }
        }
    })
)

所以我得到了相同的错误消息:

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

要修复此问题,我只需要告诉TypeScript我的映射函数返回了Action数组:

import { Action } from '@ngrx/store';
...
    switchMap((action) => {
        return action.cart.flatMap((cartItem: CartItem) : Action[] => {
...

此外,使用Action[]进行输入比使用any更安全!

答案 7 :(得分:0)

就我而言,我在rxjs运算符之一中使用了lodash运算符。原来,我没有@types/lodashnpm i -D @types/lodash之后,我的问题解决了。

答案 8 :(得分:0)

我为此问题苦了一段时间,直到最后才发现VS代码自动从某个库而不是Observable导入了rxjs

希望这可以节省不必要的头部撞击。

答案 9 :(得分:0)

我在我的项目中遇到了这个错误并通过添加这个导入来解决它:

import { Observable, of as observableOf, of } from 'rxjs';

答案 10 :(得分:-1)

我也看到了类似的错误。

Type 'Observable<unknown>' is not assignable to type 'Observable<Action> | ((...args: any[]) => Observable<Action>)'

我确定最快可能发生的方法是在|分隔符之后。 该类型通常为Observable<{something}>Observable<{something | another}>。有一个|分隔符,第二项不是Observable。这可能是问题所在。

例如,如果可观察对象期望具有Observable<Action>,但是有一些管道运算符返回Observable<Action>以外的值。错误消息中的意外类型将附加到预期类型,因为对于“可观察到的”,T在((...args: any[]) => Observable<Action>)中不存在

我对邮件的解释是

对象的内部类型未知,因为我们不知道期望哪种类型Observable<Action> = Action((...args: any[]) => Observable<Action>) =未知

如果问题不是立即显而易见的,我只是逐个注释每个管道运算符,然后看看错误是否会解决。如果是这样,那么现在我知道此操作员是问题所在,而不是我专注于操作员并找到问题。

我有兴趣阅读其他用户的回复。这两种方式总是将我指向正确的方向。