How to type Redux actions and Redux reducers in TypeScript?

后端 未结 20 2020
旧时难觅i
旧时难觅i 2020-12-13 03:39

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

相关标签:
20条回答
  • 2020-12-13 04:36

    Here is how can you do it with redux-fluent:

    0 讨论(0)
  • 2020-12-13 04:39

    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

    0 讨论(0)
提交回复
热议问题