Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

541
Visualizações
TS2339: Property 'tsReducer' does not exist on type 'DefaultRootState'

Struggling with the above question. Seen similar questions but cannot figure it out.

The below code is me attempting to open and close a dialog using TypeScript for first time in an existing React project which uses .js and .jsx.

import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import {useDispatch, useSelector} from 'react-redux';
import {closeTsDialog} from '../actions/tsDialog'
import {ActionTypes} from '../actions/types';

const TsApp = (): JSX.Element => {
    const dispatch = useDispatch();

// ERROR SHOWS UP ON LINE BELOW "state?.tsReducer?.isDialogOpen"
    const isDialogOpen = useSelector(state => state?.tsReducer?.isDialogOpen);
    const state = useSelector(s => s);
    console.log('->>>>>> state', state);


    // main tsx excluded to allow for posting on stackoverflow
};


export default TsApp;
import {TsDialogAction} from "../actions/tsDialog";


const initialState = {
    id: 0,
    isDialogOpen: false
};

const tsReducer = (state: TsDialogAction = initialState, action: Action) => {
    switch (action.type) {
        case ActionTypes.closeDialog: {
            return {...state, isDialogOpen: false};
        }
        case ActionTypes.openDialog: {
            return {...state, isDialogOpen: true};
        }
        default:
            return state;
    }
};

export default tsReducer;

import {ActionTypes} from './types';

export interface TsDialogAction { isDialogOpen: boolean number: number }

export interface CloseTsDialog { type: ActionTypes.closeDialog payload: TsDialogAction }

export interface OpenTsDialog { type: ActionTypes.openDialog payload: TsDialogAction }

export interface Increment { type: ActionTypes.increment payload: TsDialogAction }

export interface Decrement { type: ActionTypes.decrement payload: TsDialogAction }

export const closeTsDialog = (id: number) => ({type: ActionTypes.closeDialog, payload: id}); export const openTsDialog = (id: number) => ({type: ActionTypes.openDialog, payload: id}); export const incrementAction = (id: number) => ({type: ActionTypes.increment, payload: id}); export const decrementAction = (id: number) => ({type: ActionTypes.decrement, payload: id});

over 4 years ago · Santiago Trujillo
7 Respostas
Responde à pergunta

0

You need to declare the type of the state argument in your selector, like:

const isDialogOpen = useSelector( (state: RootState) => state.tsReducer.isDialogOpen);

Please see the Redux docs on TypeScript usage, as well as the React-Redux docs page on static typing for examples.

(Also, as a stylistic note: please don't call that tsReducer in your root state. Give it a name that matches the data it's handling, like state.ui.)

over 4 years ago · Santiago Trujillo Relatório

0

It is complaining about the type. Quick solution would be adding any as state type.

Proper solution will require following two steps:

  1. Create RootState type in Root Reducer.
export const rootReducer = combineReducers({
  dashboard: dashboardReducer,
  user: userReducer
});

export type RootState = ReturnType<typeof rootReducer>
  1. Provide RootState type to state object.
  let userData = useSelector((state: RootState) => {
    return state.user.data;
  });
over 4 years ago · Santiago Trujillo Relatório

0

For me, a better solution than specifying state in useSelector would be as below.
As in the node_modules/@types/react-redux/index.d.ts, you can use module augmentation.

/**
 * This interface can be augmented by users to add default types for the root state when
 * using `react-redux`.
 * Use module augmentation to append your own type definition in a your_custom_type.d.ts file.
 * https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation
 */
// tslint:disable-next-line:no-empty-interface
export interface DefaultRootState {}

Do as below

  1. Export AppState in reducer src/reducer/index.ts
const reducers = combineReducers({
  userReducer,
});

export type AppState = ReturnType<typeof reducers>;
  1. Create new your_custom_type.d.ts. (I prefer react-redux.d.ts).
    In src/@types/your_custom_type.d.ts
import 'react-redux';

import { AppState } from '../reducers';

declare module 'react-redux' {
  interface DefaultRootState extends AppState { };
}
  1. Add typeRoots in tsconfig.json
{
  "compilerOptions": {
    ...
    "typeRoots": ["src/@types"]
  }
}

You can use as below without specifying AppState

import React, { memo } from 'react';
import { useSelector } from 'react-redux';

export default memo(() => {
  const isLoggedIn = useSelector(
    ({ userReducer }) => userReducer.isLoggedIn
  );
  return <div>{isLoggedIn}</div>;
});
over 4 years ago · Santiago Trujillo Relatório

0

If you are using react-redux, another out of the box solution would be to use RootStateOrAny.

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

// and then use it like so in your component
...
const authState = useSelector((state: RootStateOrAny) => state.auth);
...


over 4 years ago · Santiago Trujillo Relatório

0

These are useful articles.

  1. https://redux.js.org/recipes/usage-with-typescript#define-root-state-and-dispatch-types
  2. https://redux.js.org/recipes/usage-with-typescript#define-typed-hooks

So first define RootState and AppDispatch like following:

//at store/index.ts
const rootReducer = combineReducers({
  tsReducer: tsReducer
});
const store = createStore(rootReducer)

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

And then define hooks (useAppDispatch, useAppSelector) can be used in components.

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

export const useAppDispatch = () => useDispatch<AppDispatch>()
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector

And use it on component like following:

import {useAppSelector} from '../store/hooks'
//...
const TsApp = (): JSX.Element => {
    const dispatch = useDispatch();

// ERROR should be fixed
    const isDialogOpen = useAppSelector(state => state.tsReducer.isDialogOpen);
};
over 4 years ago · Santiago Trujillo Relatório

0

it is just about types that you need to satisfy to this hook, useSelector accepts DefaultRootState type, you can override its default types through this

type User = {
  firstname: string;
  lastname: string;
};
type SelectorTypes = {
  users: User[];
  //...other reducers
};
const router = useSelector<SelectorTypes>((state) => state.users);
over 4 years ago · Santiago Trujillo Relatório

0

this worked for me

import { RootStateOrAny, useSelector } from "react-redux"

const search = useSelector((state: RootStateOrAny) => state.searchObj.value)
over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda