Typing Redux Toolkit Slices and Thunks
Use createSlice and createAsyncThunk with full type inference.
Typing Redux Toolkit Slices and Thunks is a free TypeScript Academy lesson on CoddyKit — lesson 1 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the TypeScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Why Type Redux Toolkit?
Redux Toolkit (RTK) includes excellent TypeScript support. Proper typing ensures actions, state, and async thunks are all type-safe without manual type assertions.
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";Typing the State Interface
Define your slice state as a TypeScript interface before creating the slice.
interface UserState {
users: User[];
loading: boolean;
error: string | null;
}
const initialState: UserState = {
users: [],
loading: false,
error: null,
};createSlice with Typed State
Pass the state type as a generic to ensure reducers receive correctly typed state.
const userSlice = createSlice({
name: "users",
initialState,
reducers: {
setLoading(state, action: PayloadAction<boolean>) {
state.loading = action.payload; // state: UserState — typed
},
},
});PayloadAction Typing
Use PayloadAction from RTK to type the action.payload in reducers.
import { PayloadAction } from "@reduxjs/toolkit";
reducers: {
addUser(state, action: PayloadAction<User>) {
state.users.push(action.payload); // action.payload: User
},
}createAsyncThunk with Types
Provide types for return value, thunk argument, and thunk API config.
const fetchUsers = createAsyncThunk<User[], void, { rejectValue: string }>(
"users/fetchAll",
async (_, { rejectWithValue }) => {
try {
return await api.getUsers();
} catch (e) {
return rejectWithValue("Failed to fetch");
}
}
);Handling Thunk Actions in extraReducers
Use the builder callback API for fully typed handling of pending/fulfilled/rejected thunk actions.
const userSlice = createSlice({
name: "users",
initialState,
reducers: {},
extraReducers: (builder) => {
builder
.addCase(fetchUsers.pending, (state) => { state.loading = true; })
.addCase(fetchUsers.fulfilled, (state, action) => {
state.users = action.payload; // action.payload: User[]
state.loading = false;
})
.addCase(fetchUsers.rejected, (state, action) => {
state.error = action.payload ?? "Unknown error";
});
},
});Typed RootState and AppDispatch
Export typed RootState and AppDispatch from the store file for use in selectors and hooks.
import { configureStore } from "@reduxjs/toolkit";
const store = configureStore({ reducer: { users: userSlice.reducer } });
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;Typed useSelector and useDispatch
Create typed versions of the Redux hooks to avoid repeating type assertions in every component.
import { useDispatch, useSelector, TypedUseSelectorHook } from "react-redux";
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;RTK Query Typing
RTK Query generates fully typed hooks from your endpoint definitions — no manual response typing needed.
const api = createApi({
reducerPath: "api",
baseQuery: fetchBaseQuery({ baseUrl: "/api" }),
endpoints: (build) => ({
getUser: build.query<User, string>({
query: (id) => `/users/${id}`,
}),
}),
});
export const { useGetUserQuery } = api;Selector Typing
Write typed selectors using RootState to ensure type-safe state access.
const selectUsers = (state: RootState): User[] => state.users.users;
const selectLoading = (state: RootState): boolean => state.users.loading;Recap: Typed RTK
Redux Toolkit TypeScript: define a state interface, use PayloadAction in reducers, type createAsyncThunk generics, export RootState and AppDispatch, and create typed hook wrappers.
Quick Check
What type annotation makes action.payload in an RTK reducer type-safe?
What You Learned
Redux Toolkit TypeScript: define slice state interfaces, use PayloadAction in reducers, type createAsyncThunk with three generics, and export typed RootState/AppDispatch with hook wrappers for component use.
Frequently asked questions
Is the “Typing Redux Toolkit Slices and Thunks” lesson free?
Yes — the full text of “Typing Redux Toolkit Slices and Thunks” is free to read here on the web, and the TypeScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the TypeScript Academy course, upgrade to CoddyKit PRO.
What will I learn in “Typing Redux Toolkit Slices and Thunks”?
Use createSlice and createAsyncThunk with full type inference. You practise TypeScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start TypeScript Academy?
No prior experience is required. TypeScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 1 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Typing Redux Toolkit Slices and Thunks” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this TypeScript Academy lesson?
Yes. Every TypeScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Typing Redux Toolkit Slices and Thunks
- Zustand Store Typing Patterns
- XState: Typed State Machines
- Derived State and Selectors with Types