Ir al contenido principal
Traducción Beta No Oficial

Esta página fue traducida por PageTurner AI (beta). No está respaldada oficialmente por el proyecto. ¿Encontraste un error? Reportar problema →

Inicio Rápido con TypeScript en Redux Toolkit

Qué aprenderás
  • Cómo configurar y usar Redux Toolkit y React-Redux con TypeScript
Requisitos previos

Introducción

¡Bienvenido al tutorial de inicio rápido de Redux Toolkit con TypeScript! Este tutorial mostrará brevemente cómo usar TypeScript con Redux Toolkit y React-Redux.

Esta página se centra únicamente en cómo configurar los aspectos de TypeScript. Para explicaciones sobre qué es Redux, cómo funciona y ejemplos completos de cómo usar Redux Toolkit, consulta los tutoriales enlazados en la página "Índice de Tutoriales".

Redux Toolkit ya está escrito en TypeScript, por lo que sus definiciones de tipos TS están integradas.

React Redux también está escrito en TypeScript a partir de la versión 8 e incluye sus propias definiciones de tipos.

La plantilla Redux+TS para Create-React-App incluye un ejemplo funcional de estos patrones ya configurado.

Configuración del Proyecto

Definir Tipos de Estado Raíz y Dispatch

La API configureStore de Redux Toolkit no debería requerir tipados adicionales. Sin embargo, convendrá extraer los tipos RootState y Dispatch para poder referenciarlos cuando sea necesario. Inferir estos tipos directamente desde el store garantiza que se actualicen correctamente al añadir más slices de estado o modificar la configuración de middleware.

Dado que son tipos, es seguro exportarlos directamente desde tu archivo de configuración del store (como app/store.ts) e importarlos en otros archivos.

app/store.ts
import { configureStore } from '@reduxjs/toolkit'
// ...

export const store = configureStore({
reducer: {
posts: postsReducer,
comments: commentsReducer,
users: usersReducer
}
})

// Infer the `RootState`, `AppDispatch`, and `AppStore` types from the store itself
export type RootState = ReturnType<typeof store.getState>
// Inferred type: {posts: PostsState, comments: CommentsState, users: UsersState}
export type AppDispatch = typeof store.dispatch
export type AppStore = typeof store

Definir Hooks Tipados

Aunque es posible importar los tipos RootState y AppDispatch en cada componente, es mejor crear versiones tipadas de los hooks useDispatch y useSelector para usar en tu aplicación. Esto es importante por varias razones:

  • Para useSelector, evita tener que escribir (state: RootState) cada vez

  • Para useDispatch, el tipo Dispatch predeterminado no reconoce los thunks. Para enviar thunks correctamente, necesitas usar el tipo personalizado AppDispatch del store que incluye los tipos de middleware thunk, y usarlo con useDispatch. Añadir un hook useDispatch pre-tipado evita que olvides importar AppDispatch donde se necesite.

Dado que son variables reales y no tipos, es importante definirlas en un archivo separado como app/hooks.ts, no en el archivo de configuración del store. Esto permite importarlas en cualquier componente que necesite usar los hooks y evita posibles problemas de dependencias circulares en las importaciones.

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

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

Uso en la Aplicación

Definir Tipos de Estado y Acciones del Slice

Cada archivo de slice debe definir un tipo para su estado inicial, para que createSlice pueda inferir correctamente el tipo de state en cada reducer case.

Todas las acciones generadas deben definirse usando el tipo PayloadAction<T> de Redux Toolkit, que toma como argumento genérico el tipo del campo action.payload.

Puedes importar con seguridad el tipo RootState desde el archivo del store aquí. Es una importación circular, pero el compilador de TypeScript puede manejarlo correctamente para tipos. Esto puede ser necesario para casos de uso como escribir funciones selectoras.

features/counter/counterSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit'
import type { RootState } from '../../app/store'

// Define a type for the slice state
export interface CounterState {
value: number
}

// Define the initial state using that type
const initialState: CounterState = {
value: 0
}

export const counterSlice = createSlice({
name: 'counter',
// `createSlice` will infer the state type from the `initialState` argument
initialState,
reducers: {
increment: state => {
state.value += 1
},
decrement: state => {
state.value -= 1
},
// Use the PayloadAction type to declare the contents of `action.payload`
incrementByAmount: (state, action: PayloadAction<number>) => {
state.value += action.payload
}
}
})

export const { increment, decrement, incrementByAmount } = counterSlice.actions

// Other code such as selectors can use the imported `RootState` type
export const selectCount = (state: RootState) => state.counter.value

export default counterSlice.reducer

Los creadores de acciones generados estarán correctamente tipados para aceptar un argumento payload basado en el tipo PayloadAction<T> que proporcionaste para el reducer. Por ejemplo, incrementByAmount requiere un number como argumento.

En algunos casos, TypeScript puede restringir innecesariamente el tipo del estado inicial. Si esto ocurre, puedes solucionarlo haciendo una conversión de tipo del estado inicial usando as, en lugar de declarar el tipo de la variable:

// Workaround: cast state instead of declaring variable type
const initialState = {
value: 0
} as CounterState

Usar hooks tipados en componentes

En los archivos de componentes, importa los hooks previamente tipados en lugar de los hooks estándar de React-Redux.

features/counter/Counter.tsx
import React from 'react'

import { useAppSelector, useAppDispatch } from 'app/hooks'

import { decrement, increment } from './counterSlice'

export function Counter() {
// The `state` arg is correctly typed as `RootState` already
const count = useAppSelector(state => state.counter.value)
const dispatch = useAppDispatch()

// omit rendering logic
}

Ejemplo completo de la aplicación de contador

Aquí tienes la aplicación de contador completa en TypeScript como un CodeSandbox en funcionamiento:

¿Qué sigue?

Recomendamos seguir el tutorial completo "Redux Essentials", que cubre todas las piezas clave incluidas en Redux Toolkit, qué problemas resuelven y cómo usarlas para construir aplicaciones del mundo real.

También puedes leer el tutorial "Redux Fundamentals", que te dará una comprensión completa de cómo funciona Redux, qué hace Redux Toolkit y cómo usarlo correctamente.

Finalmente, consulta la página "Uso con TypeScript" para obtener detalles extensos sobre cómo usar las APIs de Redux Toolkit con TypeScript.