This error occurs when using Redux Toolkit's createAsyncThunk function without providing the required type parameter. The type parameter is a string that identifies the thunk action and is used to generate Redux action type constants. The fix involves providing a unique string identifier as the first argument to createAsyncThunk.
The `createAsyncThunk` function from Redux Toolkit requires a type parameter as its first argument. This type is a string that serves as a unique identifier for the asynchronous thunk action. Redux Toolkit uses this string to generate three Redux action type constants automatically: 1. `{type}/pending` - Dispatched when the async operation starts 2. `{type}/fulfilled` - Dispatched when the async operation succeeds 3. `{type}/rejected` - Dispatched when the async operation fails This error typically appears in TypeScript projects when the type parameter is missing or incorrectly typed. The error message "Thunk action type is required for createAsyncThunk" is a TypeScript compilation error that prevents the code from building, not a runtime error. The type parameter is essential because Redux actions need unique type strings to distinguish them in reducers and middleware. Without this parameter, Redux Toolkit cannot generate the proper action types, leading to type errors in TypeScript or unexpected behavior in JavaScript.
First, verify you're importing createAsyncThunk correctly from Redux Toolkit:
// Correct import
import { createAsyncThunk } from '@reduxjs/toolkit';
// Incorrect imports that may cause issues:
// import createAsyncThunk from '@reduxjs/toolkit'; // Wrong - not a default export
// import { createAsyncThunk } from 'redux'; // Wrong - not from Redux ToolkitEnsure you have the correct version installed:
npm list @reduxjs/toolkit
# Should show version 1.9.0 or higher for best TypeScript supportThe createAsyncThunk function requires a type string as its first parameter. This should be a descriptive string in the format domain/actionName:
// Correct usage with type parameter
const fetchUserById = createAsyncThunk(
'users/fetchById', // ← REQUIRED type parameter
async (userId: number) => {
const response = await fetch(`/api/users/${userId}`);
return response.json();
}
);
// Also valid with template literal
const updateUser = createAsyncThunk(
`users/update`,
async (userData: User) => {
// async logic
}
);The type string should follow Redux conventions:
- Use lowercase with forward slashes: 'domain/action'
- Be descriptive: 'todos/addTodo' not 'add'
- Be unique across your application
If you're using TypeScript, ensure your tsconfig.json has proper settings:
{
"compilerOptions": {
"strict": true,
"noImplicitAny": true,
"strictNullChecks": true,
// These help catch type errors early
}
}If you're migrating from JavaScript to TypeScript, you might need to add explicit type annotations:
// Before (JavaScript style)
const fetchData = createAsyncThunk(async () => {
// ...
});
// After (TypeScript with explicit types)
const fetchData = createAsyncThunk(
'data/fetch', // Explicit type parameter
async () => {
// ...
}
);If you need to access the thunkApi object (containing dispatch, getState, extra, or rejectWithValue), you must define generic type arguments:
interface User {
id: number;
name: string;
}
interface ThunkApiConfig {
state: RootState;
dispatch: AppDispatch;
extra: { api: AxiosInstance };
rejectValue: string; // Custom error type
}
const fetchUser = createAsyncThunk<
User, // Return type of payload creator
number, // First argument to payload creator (userId)
ThunkApiConfig // thunkApi configuration
>(
'users/fetch',
async (userId, thunkApi) => {
const { getState, dispatch, extra, rejectWithValue } = thunkApi;
try {
const response = await extra.api.get(`/users/${userId}`);
return response.data;
} catch (error) {
return rejectWithValue('Failed to fetch user');
}
}
);For simpler cases, RTK 1.9+ offers a pre-typed version:
import { createAsyncThunk } from '@reduxjs/toolkit';
const typedCreateAsyncThunk = createAsyncThunk.withTypes<{
state: RootState;
dispatch: AppDispatch;
extra: { api: AxiosInstance };
rejectValue: string;
}>();
const fetchUser = typedCreateAsyncThunk(
'users/fetch', // Still required!
async (userId: number) => {
// ...
}
);After adding the type parameter, verify the error is resolved:
1. TypeScript compilation should succeed
2. Build process should complete without errors
3. Action types should be generated correctly:
const fetchUser = createAsyncThunk('users/fetch', async (userId: number) => {
// ...
});
// Generated action types:
// fetchUser.pending.type === 'users/fetch/pending'
// fetchUser.fulfilled.type === 'users/fetch/fulfilled'
// fetchUser.rejected.type === 'users/fetch/rejected'
// Usage in reducer:
builder
.addCase(fetchUser.pending, (state) => {
state.loading = true;
})
.addCase(fetchUser.fulfilled, (state, action) => {
state.loading = false;
state.data = action.payload;
});Test your thunk in development to ensure it dispatches the correct actions.
### TypeScript Generic Parameters
createAsyncThunk has three optional generic type parameters:
createAsyncThunk<
Returned, // Return type of the payload creator
ThunkArg, // First argument to payload creator
ThunkApiConfig // Configuration for thunkApi
>When to use generics:
- Use Returned when your async function returns a specific type
- Use ThunkArg when your payload creator takes an argument
- Use ThunkApiConfig when you need typed access to thunkApi
### Common Pitfalls
1. String literals vs variables: Prefer string literals for better type inference:
// Good
createAsyncThunk('users/fetch', ...);
// Less ideal (type may be inferred as string instead of literal)
const type = 'users/fetch';
createAsyncThunk(type, ...);2. Type prefix conventions: Follow Redux Toolkit's convention of using a prefix:
- 'feature/action' (e.g., 'todos/addTodo')
- 'domain/operation' (e.g., 'auth/login')
3. Error handling with rejectWithValue: When using rejectWithValue, you must include it in your ThunkApiConfig:
createAsyncThunk<
User,
number,
{ rejectValue: string } // ← Required for rejectWithValue
>('users/fetch', async (userId, { rejectWithValue }) => {
try {
// ...
} catch {
return rejectWithValue('Error message');
}
});### Migration from JavaScript
If migrating a JavaScript project to TypeScript, you may encounter this error for all existing createAsyncThunk calls. Use a find-and-replace approach:
# Find all createAsyncThunk calls without type parameter
grep -r "createAsyncThunk(" --include="*.ts" --include="*.tsx"Add the missing type parameter following your application's naming convention.
React.FC expects children prop to be defined
React.FC no longer includes implicit children prop
Warning: You provided a `selected` prop to a form field without an `onChange` handler
You provided a 'selected' prop without an onChange handler
Failed to load source map from suspense chunk
How to fix "Failed to load source map from suspense chunk" in React
Prop spreading could cause security issues
Prop spreading could cause security issues
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency