使用打字稿简化redux thunk动作?

时间:2018-04-12 14:53:56

标签: typescript types redux redux-thunk

我目前正在项目中使用redux thunk和typescript,我想知道是否有方法可以简化代码。截至目前,我发现了这种创造这些行为的最简洁方法:

export function apiRequestDispatcher(status: string, payload?: any ): ModalActionTypes["API_REQUEST"] {
  return {
    type: "API_REQUEST",
    status: status,
    payload: payload,
  }
}

export const sendEmail = (messageDetails: IContactForm): ThunkAction<Promise<ModalActionTypes["API_REQUEST"]>, ModalActionTypes["API_REQUEST"], undefined> => {
  return (dispatch) => {
    dispatch(apiRequestDispatcher("pending"));
    return Request
    .post("/api/email")
    .send(messageDetails)
    .set("accept", "json")
    .then((response: Request.Response) => {
      return dispatch(apiRequestDispatcher("success", response));
    }).catch((error) => {
      return dispatch(apiRequestDispatcher("error", error));
    });
  };
}

我的类型定义为:

export type ModalActionTypes = { 
    MODAL_TOGGLE: { 
        modalName: string;
        type: string; 
    },
    MODAL_ON_CHANGE: { 
        type: string;
        formName: string;
        inputName: string;
        inputValue: string;
    },
    API_REQUEST: {
        type: string;
        status: string;
        payload?: any;
    }
};

我对简化最感兴趣的部分是:

export const sendEmail = (messageDetails: IContactForm): ThunkAction<Promise<ModalActionTypes["API_REQUEST"]>, ModalActionTypes["API_REQUEST"], undefined> => {

在我发现的所有示例中,上面的代码似乎具有最少的重复次数,但我上面指出的那条线对于新来者来说真的很难理解,它也会让我失望。是否可以减少代码的其他方面?

作为参考,这是redux thunk动作的官方类型定义:

export type ThunkAction<R, S, E> = (dispatch: Dispatch<S>, getState: () => S,
                                    extraArgument: E) => R;

1 个答案:

答案 0 :(得分:0)

绝对可以做到,但这很容易变得非常自以为是。我还没有找到“标准推荐方式”。

我要在这里链接我的游乐场项目,不要把它当作“参考”,因为我远不是Dan Abramov;)。 example

这里我将我的动作类型声明为类型联合。 (这个项目的主要问题是我直接在调度员-aka上使用它们:动作创建者是可选的 - 这可以被认为是一种反模式。)

export type OtherActions =
  | {
      type: "WEEK_IS_LOADING"
    }
  | {
      type: "REPLACE_WEEK"
      monday: Date
      entries: T.Timesheet_Stored[]
      projects: T.Project[]
    }

在这里,我最终结束了一个调度类型,因为默认情况似乎不会验证你投入的动作。

export type ThunkFunction<Actions, StateT> = (
  dispatcher: AnyDispatcher<Actions, StateT>,
  getState: () => StateT
) => void | Promise<void>

export interface AnyDispatcher<Actions, State> {
  (i: Actions): void
  (fn: ThunkFunction<Actions, State>): void
}

thunk动作本身被包装在一个“错误捕获器”中,如果内部被抛出,它将调度错误动作(我猜这种行为在我开始进入redux-saga时可能会被其他东西取代)。这个“错误捕获器”还推断了内部声明的函数,因此您只需要输入必要的内容。

export const Creators = errorWrapper<ActionsT, AppStateT>()({
  Init: () => async (dispatch, getState) => {
    await Creators.Replace(new Date())(dispatch)
    dispatch({ group: "OTHER", type: "RECOVER_TRACKING_STATE" })
    await Creators.TrackingRefresh()(dispatch, getState)
  },

除了我个人的事情之外,我还在最近关于reddit评论这个项目:redoodle,它专门用于使redux + TS更容易。仍然没有测试它,但看起来很有趣。开箱即用它已经具有干净的方式来创建动作创建者,减少击键次数,而且不会丢失打字。