What is the best way to cast the action parameter in a redux reducer with typescript? There will be multiple action interfaces that can occur that all extend a
Here is how can you do it with redux-fluent:
Here is how I do it:
IAction.ts
import {Action} from 'redux';
/**
* https://github.com/acdlite/flux-standard-action
*/
export default interface IAction<T> extends Action<string> {
type: string;
payload?: T;
error?: boolean;
meta?: any;
}
UserAction.ts
import IAction from '../IAction';
import UserModel from './models/UserModel';
export type UserActionUnion = void | UserModel;
export default class UserAction {
public static readonly LOAD_USER: string = 'UserAction.LOAD_USER';
public static readonly LOAD_USER_SUCCESS: string = 'UserAction.LOAD_USER_SUCCESS';
public static loadUser(): IAction<void> {
return {
type: UserAction.LOAD_USER,
};
}
public static loadUserSuccess(model: UserModel): IAction<UserModel> {
return {
payload: model,
type: UserAction.LOAD_USER_SUCCESS,
};
}
}
UserReducer.ts
import UserAction, {UserActionUnion} from './UserAction';
import IUserReducerState from './IUserReducerState';
import IAction from '../IAction';
import UserModel from './models/UserModel';
export default class UserReducer {
private static readonly _initialState: IUserReducerState = {
currentUser: null,
isLoadingUser: false,
};
public static reducer(state: IUserReducerState = UserReducer._initialState, action: IAction<UserActionUnion>): IUserReducerState {
switch (action.type) {
case UserAction.LOAD_USER:
return {
...state,
isLoadingUser: true,
};
case UserAction.LOAD_USER_SUCCESS:
return {
...state,
isLoadingUser: false,
currentUser: action.payload as UserModel,
};
default:
return state;
}
}
}
IUserReducerState.ts
import UserModel from './models/UserModel';
export default interface IUserReducerState {
readonly currentUser: UserModel;
readonly isLoadingUser: boolean;
}
UserSaga.ts
import IAction from '../IAction';
import UserService from './UserService';
import UserAction from './UserAction';
import {put} from 'redux-saga/effects';
import UserModel from './models/UserModel';
export default class UserSaga {
public static* loadUser(action: IAction<void> = null) {
const userModel: UserModel = yield UserService.loadUser();
yield put(UserAction.loadUserSuccess(userModel));
}
}
UserService.ts
import HttpUtility from '../../utilities/HttpUtility';
import {AxiosResponse} from 'axios';
import UserModel from './models/UserModel';
import RandomUserResponseModel from './models/RandomUserResponseModel';
import environment from 'environment';
export default class UserService {
private static _http: HttpUtility = new HttpUtility();
public static async loadUser(): Promise<UserModel> {
const endpoint: string = `${environment.endpointUrl.randomuser}?inc=picture,name,email,phone,id,dob`;
const response: AxiosResponse = await UserService._http.get(endpoint);
const randomUser = new RandomUserResponseModel(response.data);
return randomUser.results[0];
}
}
https://github.com/codeBelt/typescript-hapi-react-hot-loader-example