Property 'y' does not exist on type 'DefaultRootState'

I have a src/reducers/index.tsx file where I output all my reducers:

import counterReducer from '../reducers/counter';
import loggedReducer from '../reducers/isLogged';
import {combineReducers} from 'redux';

const allReducers = combineReducers({
   counter: counterReducer,
   isLogged: loggedReducer,
});

export default allReducers;

Then in my src/index.tsx:

import {Provider} from 'react-redux';

const store = createStore(allReducers);

ReactDOM.render(
   <React.Fragment>
      <Provider store={store}>
        <App />
      </Provider>,
   document.getElementById('root'),
);

And finally in my src/app.tsx I have:

import {useSelector} from 'react-redux';

const App = () => {
   const counter = useSelector(state => state.counter);
   return (
      <h1>counter {counter}</h1>
   );
};

The error is reported in the state.counter part of the useSelector:

> Property 'counter' does not exist on type 'DefaultRootState'.ts(2339)

It looks like the store is never actually created?

Here is Solutions:

We have many solutions to this problem, But we recommend you to use the first solution because it is tested & true solution that will 100% work for you.

Solution 1

Non-hacky answer inbound!

Shortest Answer:

Link to Redux Toolkit docs for creating typed react-redux hooks: https://react-redux.js.org/using-react-redux/usage-with-typescript#define-root-state-and-dispatch-types

(While this is a link to the Redux Toolkit docs, I believe this technique should still work with "vanilla" react-redux. Please someone correct me with a comment if I’m wrong.)

Short Answer:

The useSelector hook by itself is unaware of the typing that should be applied to the state you want to use. You’ll have to do a couple lines of work to earn your type safety! Utilizing the technique shown in the link, you’ll get to have the typings for your state every time you use it. You’ll create a one-line custom hook that utilizes the native useSelector hook with the inferred types from your root state to find out what your states’ types are supposed to be.

Longer Answer:

The useSelector hook by itself is unaware of the typing that should be applied to the state you want to use. To make it so that the types of your store get captured and applied to your useSelector hooks, you’ll need to jump through two small hoops. We’re also going to take care of your useDispatch hook while we’re at it.

Step 1

Let’s grab the inferred types from the store. To do this, we’ll go to where our store is created and use some Typescript magic to get the inferred types from the state:

// Copied from Redux Toolkit docs that are linked above
// store.ts

import rootReducer from './rootReducer'

const store = createStore(rootReducer)

export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch

Brief pause to unpack lines 6 and 7:

Line 6: export type RootState = ReturnType<typeof store.getState>

  • ReturnType means "The return type of the function."

  • typeof means "Tell me what the types are of this thing."

  • store.getState is a function that returns the state object that is currently in the store.

Now put those pieces together!: Whatever is being returned from store.getState, I want the types stored as the RootState variable!


Line 7: export type AppDispatch = typeof store.dispatch

  • typeof means "Tell me what the types are of this thing."
  • store.dispatch means "I want the dispatch object used to dispatch actions to the store."

Now put those pieces together!: Get the dispatch object from the store, break it down into it’s types, and store it in the AppDispatch variable!

Step 2

Now that we have the inferred types from our store and dispatch, we can apply them to our hooks. We will do this by creating a custom hook so that we don’t have to handle typing our hooks every time we go to use them:

// Copied from Redux Toolkit docs that are linked above
// hooks.ts

import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux'
import type { RootState, AppDispatch } from './store'

// Use throughout your app instead of plain `useDispatch` and `useSelector`
export const useAppDispatch = () => useDispatch<AppDispatch>()
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

Here, we are taking the types that we created in store.ts and applying them to the useDispatch and useSelector hooks that we normally use in react-redux. From now on, you’ll have your types set up for you when you use your new custom hooks!


Voila! You now have type safety in your react-redux hook implementation!

Solution 2

This works for me.

import { RootStateOrAny, useSelector } from 'react-redux';

const { domain } = useSelector(
 (state: RootStateOrAny) => state.currentSite?.site,
);

Solution 3

It was indeed a TypeScript issue. There were a few things I changed to get my app to compile and also to work with Redux. I know we shouldn’t post links but https://github.com/piotrwitek/react-redux-typescript-guide this is a great resource! Based on the examples there I fixed my issues:

I changed the useSelector to define a type to the state, this resolved the original error.

import {RootState} from 'typesafe-actions';
const counter = useSelector((state: RootState) => state.counter);

But what is RootState? RootState is a custom type created in the src/store/types.d.ts file:

import {StateType, ActionType} from 'typesafe-actions';

declare module 'typesafe-actions' {
  export type Store = StateType<typeof import('./index').default>;

  export type RootState = StateType<typeof import('./root-reducer').default>;

  export type RootAction = ActionType<typeof import('./root-action').default>;

  interface Types {
    RootAction: RootAction;
  }
}

Solution 4

this error is the error typescript shows

I’ll explain based on mac users.
Place the mouse cursor on userSelector and click while holding down the command key. The
file in the path below will be opened
(if not open, please open it manually)
/Users/{username}/Library/Caches/typescript /3.9/node_modules/@types/react-redux/index.d.ts

And
modify the following code as

export function useSelector<TState = DefaultRootState, TSelected = unknown>()

(as
below)

export function useSelector<TState = any, TSelected = unknown>()

(If you do this, the error will probably disappear.)

The reason for the error is that
the checkJs=true setting of jsconfig.json causes vscode to check the type using typescript,
but it is an error that occurs because the type of state is not defined .

Entering any above means that you don’t care about the type of state. For
reference, to properly enter the type in JavaScript, you need to write JSDoc meticulously. In
fact, it is better to write in typescript than to do that. Do

Solution 5

This is a pain point around using the react-redux library. Whenever we make use of useSelector, TypeScript has no idea whatsoever of what type of data is inside the redux store. No information is being communicated to TypeScript from the redux side of things over to the react-redux side of things.

So we have to write additional code to help react-redux understand what type of argument this is.

Solution 6

In my case i had the same problem, first that code works fine for me but i work with sublime text to create typescript code and later that some changes i went to run npm run build and ohhh surprise the terminal shows me that does not exist on type ‘DefaultRootState’.

Umm so later that much time of search in internet i could solved that:

in your file of store.ts or store.tsx you have tha put this code:

// my code of storage
import {createStore, applyMiddleware} from 'redux'
import thunk from 'redux-thunk'
import {composeWithDevTools} from 'redux-devtools-extension'
import rootReduder from './reducers'
const initialState={}
const middleware=[thunk]
const store=createStore(rootReduder, initialState, composeWithDevTools(applyMiddleware(...middleware)))
export default store
// end of my storage code

// main solution ******
export type RootState = ReturnType<typeof store.getState>

and later that add this bit line now in the file where you call the useSelector you have that add the next lines

apply for example in your code

import {useSelector} from 'react-redux';

//call interface to solve that problem
import {RootState} from '../path/to/file/sorage';

const App = () => {
    //apply the type and solved for me
    const counter = useSelector((state:RootState) => state.counter);
    return (
        <h1>counter {counter}</h1>
    );
};

Solution 7

I have found that this works:

Redux setup:

import { combineReducers, createStore, Reducer } from "redux";

export interface StateType {
    count: number;
    color: string;
}

const initialState = {
    count: 0,
    color: "black",
};

const countReducer = (state: number = 0, action: any) => {
    switch (action.type) {
        case "INCREMENT":
            return state + 1;
        case "DECREMENT":
            return state - 1;
        default:
            return state;
    }
};

const colorReducer = (state: string = "black", action: any) => {
    switch (action.type) {
        case "CHANGE_COLOR":
            return action.color;
        default:
            return state;
    }
};

const reducers: Reducer<StateType> = combineReducers({
    count: countReducer,
    color: colorReducer,
});

export const store = createStore(reducers, initialState);

Then to use it:

import { useCallback } from "react";
import { useDispatch, useSelector } from "react-redux";
import { StateType } from "../redux/redux";

const Counter = () => {
    // get the count from the store
    const count = useSelector((state: StateType) => state.count);

    console.log(count);
    const dispatch = useDispatch();

    const increment = useCallback(() => {
        dispatch({ type: "INCREMENT" });
    }, [dispatch]);

    const decrement = useCallback(() => {
        dispatch({ type: "DECREMENT" });
    }, [dispatch]);

    return (
        <div>
            {count}
            <button onClick={increment}>Increment</button>
            <button onClick={decrement}>Decrement</button>
        </div>
    );
};

export default Counter;

Solution 8

The Only Solution is to set the Type of your state

try this

const counter = useSelector(state:any => state.counter);

Note: Use and implement solution 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply