本人在写reducer中的action类的时候发现一些问题。为啥我的类型检查没有,过不了。后面实现了改功能,特在此记一笔。好记性不如烂笔头。
效果
我们就是要实现一个类似上图的效果,在每一个type中,action的类型是不一样。实现方式看下面的成功案例
成功案例
实现的业务场景,我想实现一个用户管理的功能,可以新增用户,删除,修改用户等。
每一个功能都是独立的并且所需要的参数是不一样的,所以做了以下类型检查。
公共类型
// common.ts // 公共类型 // 枚举每一个type类型。我是使用的枚举类型 export enum EUserListActionTypes { 'add' = 'add', 'del' = 'del', 'upa' = 'upa', 'setMore' = 'setMore' } /** * 每一个用户的对象类型 */ export interface IUserObj { id: string, name: string, age?: number } /** * 修改用户的类型,id必选,其他的参数可选 */ export type updateUser = { id: string } & Partial<IUserObj> /** * 整个state的类型,里面包含一个用户列表 */ export type userList = { userList: IUserObj[] } /** * 公共的action类型,一个泛型,必须包含两个属性,一个type,一个payload */ interface Action<T extends string, P> { type: T, payload: P } // 新增用户的action传值函数的返回值 export type addAction = Action<EUserListActionTypes.add, IUserObj> // 修改用户的action传值函数的返回值 export type upaAction = Action<EUserListActionTypes.upa, updateUser> // 删除用户的action传值函数的返回值 export type delAction = Action<EUserListActionTypes.del, Extract<{ id: string },updateUser> > // 设置用户列表的action传值函数的返回值 export type setMoreAction = Action<EUserListActionTypes.setMore, IUserObj[]> // 对于reducer的action的联合类型 export type ActionType = addAction | upaAction | delAction | setMoreAction
action
类型写好了了后,写action创造函数。如下:
import { addAction, delAction, EUserListActionTypes, IUserObj, setMoreAction, upaAction, updateUser, userList } from "../types/common"; /** * create an add userList action * @param payload * @returns */ export const createAddUserList = (payload: IUserObj): addAction => ({ type: EUserListActionTypes.add, payload }) /** * create a update userList action * @param payload * @returns */ export const createUpdateUserList = (payload: updateUser): upaAction => ({ type: EUserListActionTypes.upa, payload }) /** * create a delete userList action by id * @param payload * @returns */ export const createDelUserList = (payload: { id: string }): delAction => ({ type: EUserListActionTypes.del, payload }) /** * set more data in userList * @param payload * @returns */ export const createSetMoreUserList = (payload: IUserObj[]): setMoreAction => ({ type: EUserListActionTypes.setMore, payload })
最后写reducer
import { ActionType, EUserListActionTypes, userList } from "../types/common" const initialState: userList = { userList: [ { id: '1', name: 'cll', age: 12 }, { id: '2', name: 'twinkle', age: 13 }, ] } /** * userList reducer */ export default (state: userList = initialState, action: ActionType) => { switch (action.type) { case EUserListActionTypes.add: return ({ userList: [...state.userList, action.payload] }) case EUserListActionTypes.upa: return state.userList.map(p => p.id === action.payload.id ? { ...p, ...action.payload } : p) case EUserListActionTypes.del: return state.userList.filter(f => f.id !== action.payload.id) case EUserListActionTypes.setMore: return ({ userList: [...state.userList, ...action.payload] }) default: return state } }