how to properly type the reducer
See original GitHub issueRelated to https://github.com/supasate/connected-react-router/issues/173
versions:
- connected-react-router 5.0.1
- react 16.6.3
- react-router 4.4.0-beta.6
- redux 4.0.1
- react-redux 5.1.1
I’m trying to declare my root state but I keep getting errors on History which I haven’t been able to resolve after hours.
reducer.ts
const persistConfig: PersistConfig = {
key: "root",
storage: localStorage,
};
export type RootState = ApiState &
FirebaseState & {
router: Reducer<RouterState, LocationChangeAction>;
};
// connected-react-router v5 requires exporting a function accepting history
const createRootReducer: Reducer<RootState> = (history?: History) =>
persistReducer(
persistConfig,
combineReducers({
api,
auth,
firebase: persistReducer(
{
key: "firepersist",
storage: localStorage,
stateReconciler: hardSet,
},
firebaseReducer,
),
router: connectRouter(history),
ui,
...otherReducers,
}),
);
export default createRootReducer;
type check
$ tsc --project tsconfig.json
src/reducers/index.ts:52:7 - error TS2322: Type '(history?: History<any> | undefined) => Reducer<{ application: any; contact: any; faq: any; mediaList: any; releases: any; api: {}; auth: { isLoaded: boolean; isEmpty: boolean; userId: any; }; firebase: any; router: {}; ui: any; } & PersistPartial, AnyAction>' is not assignable to type 'Reducer<RootState, AnyAction>'.
Types of parameters 'history' and 'state' are incompatible.
Type 'RootState | undefined' is not assignable to type 'History<any> | undefined'.
Type 'RootState' is not assignable to type 'History<any> | undefined'.
Type 'RootState' is missing the following properties from type 'History<any>': length, action, location, push, and 7 more.
52 const createRootReducer: Reducer<RootState> = (history?: History) =>
~~~~~~~~~~~~~~~~~
src/reducers/index.ts:66:29 - error TS2345: Argument of type 'History<any> | undefined' is not assignable to parameter of type 'History<any>'.
Type 'undefined' is not assignable to type 'History<any>'.
66 router: connectRouter(history),
~~~~~~~
Found 2 errors.
error Command failed with exit code 1.
If I cannot solve this issue, I’ll change Reducer<RootState> → Reducer
and persistReducer(…) → persistReducer(…) as any
, but this wouldn’t be sane becore my exported RootState wouldn’t guarantee that the expected state is correct.
I understand that history is undefined at the beginning. Do you know of a way to say “that’s ok” this way ?
Issue Analytics
- State:
- Created 5 years ago
- Comments:5 (1 by maintainers)
Top Results From Across the Web
Redux Fundamentals, Part 3: State, Actions, and Reducers
The official Redux Fundamentals tutorial: learn how reducers update state in response to actions.
Read more >How to write clean reducers (and test them!)
When you're using reducer composition, combine your delegating cases at the bottom of your reducer. In the example of reducer composition, all ...
Read more >How to Choose the right Reducer for your Paint Project
So you know that using a reducer with your paint is important. Great! That is half the battle. Now which temperature should you...
Read more >Typing a useReducer React hook in TypeScript - Sumo Logic
We will see how to take advantage of TypeScript's discriminated unions to correctly type reducer's actions. Finally, we will introduce a ...
Read more >Replace reducer proper typing - Stack Overflow
The need to apply types goes deeper because the property {injectPageReducer: (asyncReducer: Reducer) => void;} should know that the reducer is ...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
I’m not sure if it’s the best solution, but it seems like
combineReducers
only want a function that returns aReducer
(given byredux
). It works if I explicitly cast the result asReducer
like that:The best way I ended up finding is to use the
typesafe-actions
library to property type both your actions and your reducer @kahurangitama.You can find an example here: https://github.com/Favna/ReactTSDemo/blob/master/src/store
(note: also navigate to
ProjectRoot/typings/typesafe-actions/index.d.ts
which gets overwritten with the proper RootActions as per the lib’s requirement for typesafe reducer)Edit: since the sample code above lacks connected-react-router use this as stand in for the
index.ts
file from the linked folder: