EmptyObject on useSelector and RootState Type

Viewed 343

I am using combineReducers from redux to combine multiple reducers into a root state of type RootStateType currently I have only 1 reducer called CounterReducer with returning state type of CounterStateType.

Problem - The RootStateType is also getting unioned with type EmptyObject from typescript as I hover over it in vscode (shown in the image below).

Types of RootStateType

I followed this comment from the question React-Redux useSelector typescript type for state to use the useSelector hook from 'react-redux'.and the now the my useSelector hook is also getting the EmptyObject inferred from the types of RootStateType like this Types of useSelector

My question is will this hamper the type safety of my code? as useSelector hook can also be passed an EmptyObject. or is there is any better way of using useSelector to get rid of that EmptyObject type from it?

without using @reduxjs/toolkit?

Code

store.ts

import { createStore, combineReducers } from "redux";

export type CounterStateType = {
  value: number;
};

type CounterActionType = {
  type: string;
};

const CounterInitialState = {
  value: 0,
};

const CounterReducer = (
  state: CounterStateType = CounterInitialState,
  action: CounterActionType
) => {
  switch (action.type) {
    case "INCREASE":
      return {
        value: state.value + 1,
      };
    case "DECREASE":
      return {
        value: state.value - 1,
      };
    default:
      return state;
  }
};

const rootReducer = combineReducers({
  counter: CounterReducer,
});

const store = createStore(rootReducer);

export type RootStateType = ReturnType<typeof store.getState>;
export type AppDispatchType = typeof store.dispatch;

export default store;

CounterComp.tsx

import { useSelector } from "react-redux";

import { RootStateType } from "../store/store";

import CounterButtons from "./CounterButtons";

const CounterComp = () => {
  const counter = useSelector((state: RootStateType) => {
    return state.counter.value;
  });

  return (
    <>
      <h1>{counter}</h1>
      <CounterButtons />
    </>
  );
};

export default CounterComp;

alternatively, if I would have been working with a single reducer then for example my store would have been something like

export type CounterStateType = {
  value: number;
};

const store = createStore(CounterReducer);

and useSelector hook would have been like

const counter = useSelector<CounterStateType, CounterStateType["value"]>(
    (state) => {
      return state.value;
    }
  );

which would have ensured 100% type safety.

How do I do the same with multiple reducers?

0 Answers
Related