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
複製代碼
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; }; }
複製代碼
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
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中,咱們有 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,請嘗試一下這個庫。