web-dev-qa-db-ja.com

NgRX 8エフェクト-タイプ 'Observable <unknown>'はタイプ 'Observable <Action>'に割り当てられません

NgRX 8で作業している間、同僚と私は効果を実装するときに奇妙なエラーメッセージに頻繁に直面しています。

タイプ 'Observable <unknown>'はタイプ 'Observable <Action>に割り当てることができません| ((... args:any [])=> Observable <Action>) '

タイプの問題に関連しています。メッセージが非常に不特定であり、それが完全な効果を示していることは本当に不愉快です。これは頻繁に発生し、解決が非常に困難です。

enter image description here

問題をすばやく特定するために何かできることがあるのか​​、または何らかの方法でメッセージを分解できるのか疑問に思っています。ここでは特定の解決策を探しているのではなく、「何が問題なのかをすばやく特定する方法」の手順を探しています。

ありがとう、そして乾杯!

可能性のコレクション

これまでのところ、コメントや回答からのアイデアもあります。

  • ほとんどの場合、それはおそらくアクションの問題ではありません
  • switchMapパラメータの誤った分解である可能性があります
  • RxJSオペレーターの1つがインポートされていません
  • サービスのパラメーターと戻り値が間違っていることが原因である可能性があります
  • サービスとアクションの一貫性のないタイプも理由である可能性があります
  • 何も解決せず、確信がある場合は、何も問題はありません。TypeScriptを再読み込みします。

エラーメッセージを分解するためのトリックを期待しています。

17
Felix Lemke

クイックバージョン
コメントアウトcreateEffect(() =>
IDE(VSCode)がフラグを立てるエラーを修正し、
add createEffect(() => back in。

Alternative-次のような書き換えも機能します

_someEffect$ = createEffect(() => {
  return this.actions$.pipe(
    ...
  )
})
_

追加

上記を実行した後にエラーはありませんか?型チェックは正しく機能しており、_Observable<Action>_にマッピングするか、純粋に副作用として2番目の引数_{ dispatch: false }_を追加する必要があることを通知します(つまり、アクションをディスパッチしません)。 NgRx Effects Docs を参照してください


古い回答(_@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の条件で書き直します。きれいではありませんが動作します。

29
Andrew Allen

私はまったく同じ問題を抱えていましたが、私の場合は中括弧が間違って配置されていて、インポートが欠落していることが原因でした。

これは私がそれをデバッグして解決するためにしたことです。

内部のパイプ可能な関数を個別の関数に分割します。複雑な構文とvscodeからの自動補完ブレースのため、これは私にとって最初のステップです。時々、中括弧が間違った場所にあり、見つけるのが容易ではありません。これにより、デバッグするコードがはるかに小さくなり、vscodeがサブ関数からのこの個別のエラーを強調表示するため、他のほとんどすべての問題(インポートの欠落、不適切な戻り値の型など)も解決されます。

これは私が以前持っていたものです

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

これを下に変更しました

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

また、私がこのアプローチから得たボーナスは、内側のパイプのcatchErrorブロックがトリガーされないことです(エフェクトの例に従って、それは機能するはずです)。したがって、それを外側のパイプ可能なブロックに含める必要がありました。ここでエラーがキャッチされ、期待どおりに機能します。しかし、なぜそれが機能しないのかを理解しています。

要約すると、ログインサービスは次のことを行います(エラーをスローするか、Observableをtrueで返します)。

//login.service.ts

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

お役に立てれば。

4
sumanth shankar

実際には、createActionによって作成されたアクションを関数として扱い、それを呼び出してアクションオブジェクトを返す必要があります。これをチェックしてください desc 。したがって、of(addCommentFailed)of(addCommentFailed())になります。

1
KiraAG

この問題を処理し、公式の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>>
1
apincik

ここにimport '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';

...
0
Milena

私の場合、rxjsオペレーターの1つの中でlodashオペレーターを使用しました。結局、私は@types/lodash。後npm i -D @types/lodash、私の問題は解決しました。

0
user2991036

今日同じような問題(同じエラーメッセージ)に遭遇しました。それは、TypeScriptが Array#flatMapArray#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 <unknown>'はタイプ 'Observable <Action>に割り当てることができません| ((... args:any [])=> Observable <Action>) '

これを修正するには、マッピング関数がActionの配列を返すことをTypeScriptに通知する必要がありました。

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

また、Action[]anyより安全です。

0
boehm_s