reactjs - React + Redux-Observable + Typescript - Kompilering, Argument Ej Tilldelningsbart Fel
Jag skapar en app med React och Redux-Observable. Jag är ny på detta och jag försöker skapa en epic för att utföra användarinloggningen.
Mitt epos är nedan:
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))),
),
),
);
Problemet är att jag får ett Typescript-fel på denna rad: ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION) som säger detta:
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>'.
Mina handlingar är här:
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;
Hur kan jag fixa detta utan att använda any-typer på Epic?
Svar #1
Operatorn ofType som erbjuds av redux-observable är inte det bästa sättet att särskilja unionstyper. Ett mycket bättre sätt är att använda funktionen isOfType som tillhandahålls av typesafe-actions.
import { filter } from 'rxjs/operators';
import { isOfType } from 'typesafe-actions';
Först, låt oss berätta för TypeScript om de möjliga åtgärder som används i din applikation. Din åtgärdsström bör inte definieras som ActionsObservable<Action>, utan som en ström av dina åtgärder: ActionsObservable<LoginActions>.
export const loginUserEpic = (action$: ActionsObservable<LoginActions>) =>
Nu kan vi använda predikatet isOfType tillsammans med operatorn filter. Ersätt detta:
ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION)
med detta:
filter(isOfType(LoginActionTypes.LOGIN_ACTION))
Åtgärden som passerar strömmen kommer korrekt att kännas igen som LoginAction.
