素人エンジニアの開発日記

個人開発が趣味の素人エンジニアが日記を書きます

redux-actionsをtypescriptで使いたい人へ

Reactの0→1案件でReduxを導入したんですが Action書くのだるいなぁと思ってたらこんなものを見つけました

github.com

これを使うとactionとreducerが完結にかけるらしい

// Actions
export const isLoading = (): LoginActionType => ({
  type: LOGIN,
  payload: null,
});

const loginSuccess = (result: any): LoginActionType => ({
  type: LOGIN_SUCCESS,
  payload: result,
});

const loginFail = (err: any): LoginActionType => ({
  type: LOGIN_FAIL,
  payload: err,
});

// Reducer
const login = (state = initialState, action: LoginActionType): LoginState => {
  switch (action.type) {
    case LOGIN:
      return {
        ...state,
        loading: true,
      };
    case LOGIN_SUCCESS:
      return {
        ...state,
        data: action.payload,
        loading: false,
        status: 'success',
      };
    case LOGIN_FAIL:
      return {
        ...state,
        data: action.payload,
        loading: false,
        status: 'fail',
      };
    default:
      return state;
  }
};

例えば、こんなactionとreducerが(interfaceとか色々割愛してます)

// Actions
export const loadingAction = createAction(LOGIN);
const loginSuccessAction = createAction(LOGIN_SUCCESS, (res: any) => res);
const loginFailAction = createAction(LOGIN_FAIL, (err: any) => err);

// // Reducer
const login = handleActions({
  [loadingAction.toString()]: state => ({
    ...state,
    loading: true,
  }),
  [loginSuccessAction.toString()]: (state, action) => ({
    ...state,
    data: action.payload,
    loading: false,
    status: 'success',
  }),
  [loginFailAction.toString()]: (state, action) => ({
    ...state,
    data: action.payload,
    loading: false,
    status: 'fail',
  }),
}, initialState);

こんな完結にかけちゃいます

ただ若干ts対応が弱い…

[action.toString()] にしないとエラーが出ます (もしくはactionの返り型をanyにする)

色々調べていると

github.com

このissueのコメント欄にこんなものがありました

Hello all.

I don't think the pattern of redux-actions can give a full type inferring capability. at least not yet. Also, there is no official support for typescript in redux-actions. All of these makes using redux-actions in typescript > hard and misleading.

That's why I have just published thebrodmann/deox as a good alternative to redux-actions for typescript use cases with full power of type inferring without any type information losing. I hope it makes sense.

deox がtypescript使いのredux-actionsの代わりになる」と…

半信半疑で使ってみました

// Actions
export const isLoading = createActionCreator(LOGIN);
const loginSuccess = createActionCreator(LOGIN_SUCCESS, resolve => (res: object) => resolve(res));
const loginFail = createActionCreator(LOGIN_FAIL, resolve => (err: string) => resolve(err));

// Reducer
const login = createReducer(initialState, handleAction => [
  handleAction(isLoading, state => ({
    ...state,
    loading: true,
  })),
  handleAction(loginSuccess, (state, action) => ({
    ...state,
    data: action.payload,
    loading: false,
    status: 'success',
  })),
  handleAction(loginFail, (state, action) => ({
    ...state,
    data: action.payload,
    loading: false,
    status: 'fail',
  })),
]);

記述量はそんな変わりませんね あと変なエラーも出なくなりました

github.com

The only completely functional type-safe approach to Flux that its main goals are to diminish types verbosity, repetition and complexity without losing any type information (type-safe alternative of redux-actions).

型安全な redux-actionsだよ〜って感じですかね

star数こそ劣っているものの、最終更新はdeoxのほうが新しく最近もサポートされているみたいです

  • star
    • redux-actions : 6114
    • deox : 83
  • last commit
    • redux-actions : 4 months ago
    • deox : 4 days ago

割と問題なく使えたのでtsでredux-actions導入しようと思ってる人は使ってみてはいかがでしょう