fetchSomething
is defined like this:
export const fetchSomething = createAsyncThunk(
'something',
async () => {
return Promise.resolve({name: 'jack'})
}
)
Here's the code inside the React component:
const dispatch = useAppDispatch()
const getMessages = async () => {
const result = await dispatch(fetchSomething())
return result.payload
}
result
has the correct Typescript type, while result.payload
is of type unknown
const result: PayloadAction<{name: string}, string, {arg: void, requestId: string, requestStatus: "fulfilled"}, never> | PayloadAction<unknown, string, {arg: void, requestId: string, requestStatus: "rejected", aborted: boolean, condition: boolean}, SerializedError>
I found related information on official documentation, but I don't know how to use in my example:
import { UnknownAction } from 'redux'
import { sendMessage } from './store/chat/actions'
import { RootState } from './store'
import { ThunkAction } from 'redux-thunk'
export const thunkSendMessage =
(message: string): ThunkAction<void, RootState, unknown, UnknownAction> =>
async dispatch => {
const asyncResp = await exampleAPI()
dispatch(
sendMessage({
message,
user: asyncResp,
timestamp: new Date().getTime()
})
)
}
function exampleAPI() {
return Promise.resolve('Async Chat Bot')
}
I want the getMessages
method to return the correct type Promise<{name: string}>
I queried the docs again as suggested by @timotgl, found this section, and made changes to the code, but the problem persists, The type of result.payload
is still unknown
.
export const fetchSomething = createAsyncThunk<{name: string}>(
'something',
async () => {
return Promise.resolve({name: 'jack'})
}
)
See Basic createAsyncThunk
Types:
In the most common use cases, you should not need to explicitly declare any types for the createAsyncThunk call itself.
Just provide a type for the first argument to the payloadCreator argument as you would for any function argument, and the resulting thunk will accept the same type as its input parameter. The return type of the payloadCreator will also be reflected in all generated action types.
interface MyData { // ... } const fetchUserById = createAsyncThunk( 'users/fetchById', // Declare the type your function argument here: async (userId: number) => { const response = await fetch(`https://reqres.in/api/users/${userId}`) // Inferred return type: Promise<MyData> return (await response.json()) as MyData // <-- } ) // the parameter of `fetchUserById` is automatically inferred to `number` here // and dispatching the resulting thunkAction will return a Promise of a correctly // typed "fulfilled" or "rejected" action. const lastReturnedAction = await store.dispatch(fetchUserById(3))
Take note of the thunk's return value:
// Inferred return type: Promise<MyData>
return (await response.json()) as MyData
Applying the above suggested pattern to your code:
interface Something {
name: string;
};
export const fetchSomething = createAsyncThunk(
'something',
async () => {
return Promise.resolve({ name: 'jack' }) as Something;
}
)
const dispatch = useAppDispatch()
const getMessages = async () => {
try {
const result = await dispatch(fetchSomething()).unwrap();
return result;
} catch(error) {
// ... any error handling logic ...
}
};