Despite having used Typescript and Redux separately for a few years I haven't always had a good experience putting them together. Recently, I stumbled on two tricks that have helped me immensely.
Generate Reducer Type from Initial State
When you're creating a new reducer you can use typeof
to generate the type for the reducer from your initial state. This also encourages us to fully fill out our initial state, which I find helpful for quickly understanding the purpose of each reducer.
When you export your reducer make sure to include that generated type as its return type.
const initialState = {
dogs: 4,
name: "Callie",
colors: ["red", "green", "blue"]
};
type MyReducer = typeof initialState;
export default function myReducer(state = initialState, action): MyReducer {
// ...
}
If your initial state doesn't include all of the values, you can include them as placeholder values such as null
. In those cases you can use as <type>
to indicate the intended type for that piece of state.
For example const initialState = { person: null as Person };
Export Your Entire Redux State
Once your reducers are all individually typed, you can create and export a combined ReduxState
type using Typescript's ReturnType utility. This type will contain information about every single reducer used in your application.
import { reducers } from "./reducers";
export const store = createStore(combineReducers(reducers));
export type ReduxState = ReturnType<typeof store.getState>;
Use this to type the state
argument used by your selector functions, mapStateToProps
or anywhere else that may be needed.
import { ReduxState } from "../store";
export const getDogs(state: ReduxState) {
return state.myReducer.dogs;
}
A version of these same ideas (and many others) can be found in the Usage with Types section of the redux docs.
While it doesn't cover typescript (yet!), don't forget to check out my course Redux with React Hooks which shows how much simpler redux becomes when you drop the boilerplate.
What are your favorite typescript tricks when using Redux?
Top comments (3)
Hmm. Yeah, we show inferring
RootState
from the root reducer in our docs, but we normally show explicitly writing out slice reducer state types. Obviously you can infer that from the initial state, we just hadn't shown that specifically. Could probably throw a line into the docs mentioning that.FWIW, our TS docs are here:
@markerikson I like this approach, because it encourages filling out the initial state and it's less overall code, but they both work well. I updated my article with a link to the redux docs!
Okay that looks way better, thanks!