Frontend Quick Tips #4 Strong Typings For Redux State
Those may be some patterns explained in JS code on real-life examples or some techniques for better code.
Problem
You want your Redux state to be strongly typed using TypeScript and integrate with the IDE for features such as auto-completion, real-time errors and easier refactors.
Solution
We can use typesafe-actions (link), a package created and maintained by Piotr Witek. It is a set of helper functions which allows us to easily create and manage Redux state.
Creating root reducer
src/store/rootReducer.ts
A reducer is a function that returns the next state tree, given the current state tree and an action to handle. The root reducer is the combination of all reducers from the application.
import { combineReducers } from "redux";
import gridReducer from "./ducks/grid/reducer";
const rootReducer = combineReducers({
grid: gridReducer
});
export default rootReducer;
We can generate the state tree shape type by using the StateType(documentation) helper which infers state object type from reducer functions.
import { StateType } from "typesafe-actions";
type RootState = StateType<typeof rootReducer>
// { grid: GridStateShape }
Creating helper types
You can define global types and extend default typesafe-actions definitions for better IDE integration and auto-completion.
Creating an action creator
src/store/ducks/grid/actionCreators.ts
typesafe-actions exposes a createAction helper. It will automatically create a standardised action creator with strong types which you can use inside a dispatch function.
Creating a reducer
src/store/ducks/grid/reducer.ts
typesafe-actions exposes a createReducer helper to create typesafe reducers. Given an action creator, you can assign action handlers which accept state and action arguments whose types will get automatically narrowed.
Note that you can always use the standard switch/conditional reducers and get the types narrowed by using the getType(documentation) helper: