Quick simple guide on making Redux-Observable works with TypeScript
This is a guide I written on stack overflow, which I plan to rewrite it into a simple post.
You can checkout React Redux Typescript Guide for the details in here for all the standard way of doing when using React, Redux and Redux-Observable.
Introduction
This guide I would like to talk a bit about using Redux-Observable alongside with TypeScript and make the types work out of the box.
I will be using typesafe-actions
library to achieve the types. (GitHub for typesafe-actions)
Actions
Instead of declaring interface (types) expressively, (something like below)
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 },
};
}
use typesafe-actions
library without declaring any interface.
actions/login/LoginActions.ts
import {action} from "typesafe-actions"
export function loginSuccess(loginToken: string) {
return action(LoginActionTypes.LOGIN_SUCCESS_ACTION, { loginToken });
}
Then, all the login actions are being exported out in the model file.
actions/login/LoginActionsModel.ts
import * LoginActions from "./LoginActions";
import { ActionCreator } from "typesafe-actions";
export type LoginActionCreator = ActionCreator<typeof LoginActions>
Then export out all the actions as AllActions.
actions/index.ts
import { LoginActionCreator } from "./login/LoginActionModel";
export default type AllActions = LoginActionCreator
Epics
In the epics, import following library.
import { Epic } from "redux-observable";
import { isOfType } from "typesafe-actions";
import { filter } from "rxjs/operators";
Then simply use Epic to declare your types.
export const loginUserEpic: Epic<AllActions> = (action$) =>
action$.pipe(
filter(isOfType((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))),
),
),
);
Where the Epics is from redux-observable
library, AllActions are the actions that is input and output of the epics.
The types is as follows:
Epic<InputActions, OutputActions, Store>
Epic<Actions(Input&Output)>
In case you want to use store from redux, you need a RootState (from root reducer)
export const someEpic: Epic<AllActions, AllActions, RootState> = (action$, store$)
=> action$.pipe(
filter(isOfType(SOMETYPE)),
mergeMap(action => {
const a = store$.value.a;
return someActions(a, action.payload.b);
})
You’ve been upvoted by TeamMalaysia Community :-
To support the growth of TeamMalaysia Follow our upvotes by using steemauto.com and follow trail of @myach
Vote TeamMalaysia witness bitrocker2020 using this link vote for witness
你今天过的开心吗?来 @steemgg 玩游戏吧,决战到天亮如果不想再收到我的留言,请回复“取消”。
Hi, @superoo7!
You just got a 0.91% upvote from SteemPlus!
To get higher upvotes, earn more SteemPlus Points (SPP). On your Steemit wallet, check your SPP balance and click on "How to earn SPP?" to find out all the ways to earn.
If you're not using SteemPlus yet, please check our last posts in here to see the many ways in which SteemPlus can improve your Steem experience on Steemit and Busy.