React + Redux-Observable + Typescript - 编译,参数不可分配错误

Fel*_*ipe 8 rxjs typescript reactjs redux-observable

我正在使用React和Redux-Observable创建一个应用程序.我是新手,我正在尝试创建一个史诗来执行用户登录.

我的史诗如下:

export const loginUserEpic = (action$: ActionsObservable<Action>) =>
  action$.pipe(
    ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION),
    switchMap((action: LoginAction) =>
      ajax({
        url,
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: { email: action.payload.username, password: action.payload.password },
      }).pipe(
        map((response: AjaxResponse) => loginSuccess(response.response.token)),
        catchError((error: Error) => of(loginFailed(error))),
      ),
    ),
  );
Run Code Online (Sandbox Code Playgroud)

问题是我在这一行上收到了一个Typescript错误:ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION)这样说:

Argument of type '(source: Observable<LoginAction>) => Observable<LoginAction>' is not assignable to parameter of type 'OperatorFunction<Action<any>, LoginAction>'.
  Types of parameters 'source' and 'source' are incompatible.
    Type 'Observable<Action<any>>' is not assignable to type 'Observable<LoginAction>'.
      Type 'Action<any>' is not assignable to type 'LoginAction'.
        Property 'payload' is missing in type 'Action<any>'.
Run Code Online (Sandbox Code Playgroud)

我的行动在这里:

export enum LoginActionTypes {
  LOGIN_ACTION = 'login',
  LOGIN_SUCCESS_ACTION = 'login-sucesss',
  LOGIN_FAILED_ACTION = 'login-failed',
}

export interface LoginAction extends Action {
  type: LoginActionTypes.LOGIN_ACTION;
  payload: {
    username: string;
    password: string;
  };
}

export function login(username: string, password: string): LoginAction {
  return {
    type: LoginActionTypes.LOGIN_ACTION,
    payload: { username, password },
  };
}

export interface LoginSuccessAction extends Action {
  type: LoginActionTypes.LOGIN_SUCCESS_ACTION;
  payload: {
    loginToken: string;
  };
}

export function loginSuccess(loginToken: string): LoginSuccessAction {
  return {
    type: LoginActionTypes.LOGIN_SUCCESS_ACTION,
    payload: { loginToken },
  };
}

export interface LoginFailedAction extends Action {
  type: LoginActionTypes.LOGIN_FAILED_ACTION;
  payload: {
    error: Error;
  };
}

export function loginFailed(error: Error): LoginFailedAction {
  return {
    type: LoginActionTypes.LOGIN_FAILED_ACTION,
    payload: { error },
  };
}

export type LoginActions = LoginAction | LoginSuccessAction | LoginFailedAction;
Run Code Online (Sandbox Code Playgroud)

如何any在不使用Epic上的类型的情况下解决这个问题?

Kar*_*ski 6

ofType提供的运算符redux-observable不是区分工会类型的最佳方法。更好的方法是使用所isOfType提供的功能typesafe-actions

import { filter } from 'rxjs/operators';
import { isOfType } from 'typesafe-actions';
Run Code Online (Sandbox Code Playgroud)

首先,让我们告诉TypeScript应用程序中可能使用的操作。您的操作流不应定义为ActionsObservable<Action>,而应定义为您的操作流:ActionsObservable<LoginActions>

export const loginUserEpic = (action$: ActionsObservable<LoginActions>) =>
Run Code Online (Sandbox Code Playgroud)

现在我们可以将isOfType谓词与filter运算符一起使用。替换为:

ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION)
Run Code Online (Sandbox Code Playgroud)

有了这个:

filter(isOfType(LoginActionTypes.LOGIN_ACTION))
Run Code Online (Sandbox Code Playgroud)

流中传递的动作将正确识别为LoginAction