Skip to content

Commit

Permalink
Add example of createAsyncThunk.withTypes
Browse files Browse the repository at this point in the history
  • Loading branch information
markerikson committed Aug 19, 2022
1 parent 74e7cb4 commit daf9920
Showing 1 changed file with 25 additions and 3 deletions.
28 changes: 25 additions & 3 deletions docs/usage/usage-with-typescript.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,18 @@ export type RootState = ReturnType<typeof store.getState>
export default store
```

If you pass the reducers directly to `configureStore()` and do not define the root reducer explicitly, there is no reference to `rootReducer`.
If you pass the reducers directly to `configureStore()` and do not define the root reducer explicitly, there is no reference to `rootReducer`.
Instead, you can refer to `store.getState`, in order to get the `State` type.

```typescript
import { configureStore } from '@reduxjs/toolkit'
import rootReducer from './rootReducer'
const store = configureStore({
reducer: rootReducer
reducer: rootReducer,
})
export type RootState = ReturnType<typeof store.getState>
```
### Getting the `Dispatch` type
If you want to get the `Dispatch` type from your store, you can extract it after creating the store. It is recommended to give the type a different name like `AppDispatch` to prevent confusion, as the type name `Dispatch` is usually overused. You may also find it to be more convenient to export a hook like `useAppDispatch` shown below, then using it wherever you'd call `useDispatch`.
Expand Down Expand Up @@ -489,6 +488,8 @@ const wrappedSlice = createGenericSlice({

## `createAsyncThunk`

### 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.
Expand Down Expand Up @@ -518,8 +519,12 @@ const fetchUserById = createAsyncThunk(
const lastReturnedAction = await store.dispatch(fetchUserById(3))
```

### Typing the `thunkApi` Object

The second argument to the `payloadCreator`, known as `thunkApi`, is an object containing references to the `dispatch`, `getState`, and `extra` arguments from the thunk middleware as well as a utility function called `rejectWithValue`. If you want to use these from within the `payloadCreator`, you will need to define some generic arguments, as the types for these arguments cannot be inferred. Also, as TS cannot mix explicit and inferred generic parameters, from this point on you'll have to define the `Returned` and `ThunkArg` generic parameter as well.

#### Manually Defining `thunkApi` Types

To define the types for these arguments, pass an object as the third generic argument, with type declarations for some or all of these fields:

```ts
Expand Down Expand Up @@ -662,6 +667,23 @@ const handleUpdateUser = async (userData) => {
}
```

#### Defining a Pre-Typed `createAsyncThunk`

As of RTK 1.9, you can define a "pre-typed" version of `createAsyncThunk` that can have the types for `state`, `dispatch`, and `extra` built in. This lets you set up those types once, so you don't have to repeat them each time you call `createAsyncThunk`.

To do this, call `createAsyncThunk.withTypes<>()`, and pass in an object containing the field names and types for any of the fields in the `AsyncThunkConfig` type listed above. This might look like:

```ts
const createAppAsyncThunk = createAsyncThunk.withTypes<{
state: RootState
dispatch: AppDispatch
rejectValue: string
extra: { s: string; n: number }
}>()
```

Import and use that pre-typed `createAppAsyncThunk` instead of the original, and the types will be used automatically:

## `createEntityAdapter`

Typing `createEntityAdapter` only requires you to specify the entity type as the single generic argument.
Expand Down

0 comments on commit daf9920

Please sign in to comment.