← Back to TypeScript Course | Chapter 14: TypeScript with React | Lesson 8 of 8

Typing Redux

Redux applications benefit greatly from TypeScript because state, actions, reducers, and dispatches can all be checked at compile time. Modern Redux Toolkit provides helpers such as configureStore, createSlice, and typed hooks for a safe React integration.
Syntax
typescript
interface SliceState {
  propertyName: type;
}

function reducerName(state: SliceState = initialState, action: ActionType): SliceState {
  return state;
}

Defining Redux State

Defining Redux state starts with a typed interface for the slice's shape, which becomes the return type of its reducer and the type every component reading from that slice can rely on.

Example: Defining Redux State

typescript
interface CounterState {
  value: number;
}
const initialState: CounterState = { value: 0 };
function counterReducer(state = initialState, action: { type: string }): CounterState {
  return state;
}
console.log(counterReducer(undefined, { type: "init" }));

Typing Payloads

Typing action payloads means each action's payload field has its own specific type matching what that action actually carries, so dispatching an action with the wrong payload shape is caught before runtime.

Example: Typing Payloads

typescript
interface IncrementAction {
  type: "increment";
  payload: number;
}
const action: IncrementAction = { type: "increment", payload: 5 };
console.log(action);

Typing the Redux Store

Typing the store itself usually means exporting RootState (inferred from the store's own getState) and AppDispatch types, which every typed hook in the app then reuses instead of redefining.

Example: Typing the Redux Store

typescript
interface RootState {
  counter: { value: number };
}
// type AppDispatch = typeof store.dispatch;
const state: RootState = { counter: { value: 0 } };
console.log(state);

Typed React Redux Hooks

Typed React-Redux hooks are built by wrapping the generic useSelector and useDispatch with your app's specific RootState and AppDispatch types, so every component gets fully typed access without repeating generics.

Example: Typed React Redux Hooks

typescript
interface RootState {
  counter: { value: number };
}
// const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
function selectCount(state: RootState): number {
  return state.counter.value;
}
console.log(selectCount({ counter: { value: 3 } }));

Typing Selectors and Redux Data

Typing selectors means annotating their input as RootState and their return type as whatever specific slice or derived value they extract, catching a typo in a state path immediately instead of returning silent undefined.

Example: Typing Selectors and Redux Data

typescript
interface RootState {
  user: { name: string } | null;
}
function selectUserName(state: RootState): string | undefined {
  return state.user?.name;
}
console.log(selectUserName({ user: { name: "Ravi" } }));
Related Topics
{# common_mistakes/chapter_summary/browser_support: on Hindi pages the view already swaps in the hi_ translation fields (or blanks these out if untranslated), so this renders correctly for both languages without a lang_code check here. #}
Common Mistakes
  1. Typing state in the reducer as any, so mistakes in the state shape are never caught.
  2. Giving actions a loose payload: any instead of one specific type per action.
  3. Using plain useSelector and useDispatch without typed versions, so state is unknown and dispatches are unchecked.
Chapter Summary
  • A React TypeScript project types props, state, and events so components are checked at compile time.
  • Hooks such as useState, useEffect, and useRef can be typed to describe the data they hold.
  • The Context API and Redux can also be typed so shared data stays consistent across components.
🔒

Chapter Quiz — Complete all 8 topics to unlock

0/8 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.