margherita pizza
margherita pizza

Reputation: 7145

React redux set type for initialState

This is my todos redcuer

import ActionType from "../types";
import { Action } from "../actions";

interface Item {
  task: string;
  priority: string;
  id: string;
  isActive: boolean;
  label: string;
}

const initialState = {
  items: [],
};

function reducer(state = initialState, action: Action) {
  switch (action.type) {
    case ActionType.ADD_ITEM:
      return { ...state, items: [action.payload, ...state.items] };

    case ActionType.CROSS_ITEM:
      return {
        ...state,
        items: state.items.map((e: Item) => {
          if (e.id === action.payload) e.isActive = false;
          return e;
        }),
      };

    default:
      return state;
  }
}
export default reducer;

This is my root reducer

import { combineReducers } from "redux";
import authReducer from "./authReducer";
import todoReducer from "./todoReducer";

const reducers = combineReducers({
  auth: authReducer,
  todo: todoReducer,
});

export default reducers;

Finally, this is the store.ts

import { createStore, applyMiddleware, compose } from "redux";
import thunk from "redux-thunk";
import rootReducer from "./reducers/index";

const middleware = [thunk];
const initialState = {};

const store = createStore(
  rootReducer,
  initialState,
  compose(
    applyMiddleware(...middleware),
    // window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
  )
);

export type State = ReturnType<typeof store.getState>;

export default store;

In my TodoList.jsx

import {State} from "../store/store"
const items = useSelector((state:State) => state.todo.items);

This gives me an error

Property 'items' does not exist on type 'never'

If I mouse hover on store.getState

enter image description here

In here I can't see todo as an array that contains items.Instead, I only see todo:never

How do I fix this error?

Upvotes: 1

Views: 1418

Answers (2)

Lin Du
Lin Du

Reputation: 102287

You could create the type for each state slice so that TS can infer the type.

todoReducer.ts:

import { AnyAction } from 'redux';
import ActionType from './types';

interface Item {
  task: string;
  priority: string;
  id: string;
  isActive: boolean;
  label: string;
}

type TodoState = {
  items: Item[];
};

const initialState: TodoState = {
  items: [],
};

function reducer(state = initialState, action: AnyAction): TodoState {
  switch (action.type) {
    case ActionType.ADD_ITEM:
      return { ...state, items: [action.payload, ...state.items] };

    case ActionType.CROSS_ITEM:
      return {
        ...state,
        items: state.items.map((e: Item) => {
          if (e.id === action.payload) e.isActive = false;
          return e;
        }),
      };

    default:
      return state;
  }
}
export default reducer;

enter image description here

"redux": "^4.1.0",
"redux-thunk": "^2.3.0",
"typescript": "^4.3.5"

Upvotes: 1

Ryan Le
Ryan Le

Reputation: 8412

You could do this instead:

export type State = ReturnType<typeof rootReducer>;

Upvotes: 0

Related Questions