使用 typesafe-actions 建立類型安全的 redux

typesafe-actions 是什麼

typesafe-actions 是一款專門爲 ts 設計的庫,可以幫助開發者減小 redux 樣板代碼,並自動爲開發者建立好類型。javascript

大佬直接異步 官方倉庫java

這個倉庫是 React 和 Redux 生態的一部分,so,若是想換個方式寫 action、reducer 和 type,能夠繼續看下去。react

如何安裝使用

在保證已經安裝好 react 和 redux 的狀況下,使用如下兩種方式安裝:ios

// NPM
npm install typesafe-actions

// YARN
yarn add typesafe-actions
複製代碼

經常使用 API 介紹

action 建立方式一:

import { action, createAction } from 'typesafe-actions';

export const add = (title: string) => action('todos/ADD', { id: cuid(), title, completed: false });
// add: (title: string) => { type: "todos/ADD"; payload: { id: string, title: string, completed: boolean; }; }

export const add = createAction('todos/ADD', action => {
  // Note: "action" callback does not need "type" parameter
  return (title: string) => action({ id: cuid(), title, completed: false });
});
// add: (title: string) => { type: "todos/ADD"; payload: { id: string, title: string, completed: boolean; }; }
複製代碼

action 建立方式二:

import { createStandardAction } from 'typesafe-actions';

export const toggle = createStandardAction('todos/TOGGLE')<string>();
// toggle: (payload: string) => { type: "todos/TOGGLE"; payload: string; }

export const add = createStandardAction('todos/ADD').map(
  (title: string) => ({
    payload: { id: cuid(), title, completed: false },
  })
);
// add: (payload: string) => { type: "todos/ADD"; payload: { id: string, title: string, completed: boolean; }; }
複製代碼

值得注意的是,以上經過這兩個 api 建立的 action,是符合 Flux 定義的 action,即 { type, paylaod, meta, error }這適用於絕大多數狀況。當官方值不能知足的狀況下,你也能夠採用自定義 action 的方式。git

action 建立方式三(自定義):

import { createCustomAction } from 'typesafe-actions';

const add = createCustomAction('todos/ADD', type => {
  return (title: string) => ({ type, id: cuid(), title, completed: false });
});
// add: (title: string) => { type: "todos/ADD"; id: string; title: string; completed: boolean; }
複製代碼

在 reducer 中使用 action

在reducer中,咱們有 getType api 來幫助咱們獲取 action 的 type:github

// reducer.ts
switch (action.type) {
    case getType(todos.add):
      // below action type is narrowed to: { type: "todos/ADD"; payload: Todo; }
      return [...state, action.payload];
    ...
複製代碼

除了官方建立 reducer 的方式外, createReducer api 也可幫助建立:npm

// using action-creators
const counterReducer = createReducer(0)
  // state and action type is automatically inferred and return type is validated to be exact type
  .handleAction(add, (state, action) => state + action.payload)
  .handleAction(add, ... // <= error is shown on duplicated or invalid actions
  .handleAction(increment, (state, _) => state + 1)
  .handleAction(... // <= error is shown when all actions are handled

  // or handle multiple actions using array
  .handleAction([add, increment], (state, action) =>
    state + (action.type === 'ADD' ? action.payload : 1)
  );

// all the same scenarios are working when using type-constants
const counterReducer = createReducer(0)
  .handleAction('ADD', (state, action) => state + action.payload)
  .handleAction('INCREMENT', (state, _) => state + 1);

counterReducer(0, add(4)); // => 4
counterReducer(0, increment()); // => 1
複製代碼

⬆ 對於對代碼質量有要求的人來講,上面這種相對於默認建立方式的滿屏 case return 更優雅redux

固然除了優雅,上面這種方式還能得到 ts 的類型加強,而不須要額外多處的引用,咱們只須要api

// types.d.ts
import { StateType, ActionType } from 'typesafe-actions';

declare module 'typesafe-actions' {
  export type Store = StateType<typeof import('./store').default>;

  export type RootState = StateType<typeof import('./store/root-reducer').default>;

  export type RootAction = ActionType<typeof import('./store/root-action').default>;

  interface Types {
    RootAction: RootAction;
  }
}
複製代碼

全部類型都自動建立完成,便可減小類型定義方面的代碼。bash

總結

這個庫減小咱們寫樣板代碼和隨處可見的類型定義,若是你使用 redux 和 ts,請嘗試一下這個庫。

相關文章
相關標籤/搜索