There are a few issues here in your code are all related. You need to properly define:
- The type of
dispatch in your fetchCountries function.
- The type of the
payload for setCountries.
- The type of your state.
- The type of your API response.
Incorrect or missing types higher up in the chain can cause issues further down. For example, when you find yourself setting a type in a .map() callback like this:
array[1].map((el: any) => {
It means that the array itself (array[1]) has the wrong type. So let's figure out where it's going wrong.
1. Dispatch Type
@T.D. Stoneheart is correct. The expected 0 arguments, but got 1 error comes from calling dispatch(...), not from calling setCountries(...).
Your definition dispatch:(() => void) says that dispatch does not take any arguments. This is obviously incorrect.
The good news is that you already have the correct type elsewhere in your code. It is the AppDispatch which you exported from your store file.
export const fetchCountries = () => {
return (dispatch: AppDispatch) => {
This fix is enough to resolve all red-underlined errors. But there are some other mistakes and omissions that you may want to fix.
2. Payload Type
If you don't explicitly set the type for setCountries(state, action), then your payload type becomes any. This is fine, but not ideal. It says that "anything goes" which can make it hard to see genuine problems.
To assign the correct type to the action, import the PayloadAction utility type for redux toolkit:
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
And use it with the type of your payload, which is an array of countries. Looking at your thunk, these seem to be string?:
reducers: {
setCountries(state, action: PayloadAction<string[]>) {
state.countryList = action.payload;
},
},
3. State Type
Remember how I said that any can hide genuine problems? If you followed step 2 then you should be seeing one of those now.
The assignment of state.countryList = action.payload; is giving an error:
Type 'string[]' is not assignable to type 'never[]'.
Your state.countryList has type never[] because it had an initial value of [] and that's all that TypeScript knows. It doesn't know that this is supposed to be an array of country ids. You can fix that by assigning a more accurate type to your `initialState.
Either do this:
const initialState = {
countryList: [] as string[],
};
Or this:
interface SliceState { // can name it whatever
countryList: string[];
}
const initialState: SliceState = {
countryList: [],
};
Having a correct type here will make it much, much easier to use data that you've selected from your state because now RootState has the correct type for the countryList property.
4. API Response Type
interface fetchedCountries {
mergedArray?: [];
}
This type is saying that the JSON from your response is an object which maybe has a property mergedArray which is an empty array. That's it.
I'm not sure what the actual data looks like, but perhaps something like this?
interface Country {
_id: string;
}
interface FetchedCountries {
mergedArray: Country[];
}
So now you don't need to use (el: any) because TypeScript already knows that el is a Country object.
.then((jsonData: FetchedCountries) => {
const countries = jsonData.mergedArray
.map(el => el._id)
.sort();
dispatch(setCountries(countries));
})
TypeScript Playground Link
setCountries()action creator, I believe, it has to be something, likeconst setCountries = (country: string) => ({type: YOUR_CORRESPONDING_ACTION_TYPE_HERE, country})