You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/api/createSlice.mdx
+14-5Lines changed: 14 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -304,16 +304,25 @@ Typing for the `create.asyncThunk` works in the same way as [`createAsyncThunk`]
304
304
305
305
A type for `state` and/or`dispatch`_cannot_beprovidedaspartofthe`ThunkApiConfig`, asthiswouldcausecirculartypes.
306
306
307
-
Instead, itisnecessarytoassertthetypewhenneeded.
307
+
Instead, itisnecessarytoassertthetypewhenneeded-`getState() as RootState`. Youmayalsoincludeanexplicitreturntypeforthepayloadfunction as well, in order to break the circular type inference cycle.
Copy file name to clipboardExpand all lines: docs/rtk-query/usage-with-typescript.mdx
+26Lines changed: 26 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -390,6 +390,32 @@ const api = createApi({
390
390
})
391
391
```
392
392
393
+
### Typing `dispatch` and `getState`
394
+
395
+
`createApi` exposes the standard Redux `dispatch` and `getState` methods in several places, such as the `lifecycleApi` argument in lifecycle methods, or the `baseQueryApi` argument passed to `queryFn` methods and base query functions.
396
+
397
+
Normally, [your application infers `RootState` and `AppDispatch` types from the store setup](../tutorials/typescript.md#define-root-state-and-dispatch-types). Since `createApi` has to be called prior to creating the Redux store and is used as part of the store setup sequence, it can't directly know or use those types - it would cause a circular type inference error.
398
+
399
+
By default, `dispatch` usages inside of `createApi` will be typed as `ThunkDispatch`, and `getState` usages are typed as `() => unknown`. You will need to assert the type when needed - `getState() as RootState`. You may also include an explicit return type for the function as well, in order to break the circular type inference cycle:
400
+
401
+
```ts no-transpile
402
+
const api =createApi({
403
+
baseQuery,
404
+
endpoints: (build) => ({
405
+
getTodos: build.query<Todo[], void>({
406
+
async queryFn() {
407
+
// highlight-start
408
+
// Cast state as `RootState`
409
+
const state =getState() asRootState
410
+
// highlight-end
411
+
const text =state.todoTexts[queryFnCalls]
412
+
return { data: [{ id: `${queryFnCalls++}`, text }] }
413
+
},
414
+
}),
415
+
}),
416
+
})
417
+
```
418
+
393
419
### Typing `providesTags`/`invalidatesTags`
394
420
395
421
RTK Query utilizes a cache tag invalidation system in order to provide [automated re-fetching](./usage/automated-refetching.mdx) of stale data.
As TS cannot combine two string literals (`slice.name`and the key of `actionMap`) into a new literal, all actionCreators created by `createSlice` are of type 'string'. This is usually not a problem, as these types are only rarely used as literals.
329
+
`createSlice` generates action type strings by combining the `name`field from the slice with the field name of the reducer function, like `'test/increment'`. This is strongly typed as the exact value, thanks to TS's string literal analysis.
330
330
331
-
In most cases that `type` would be required as a literal, the `slice.action.myAction.match`[type predicate](https://www.typescriptlang.org/docs/handbook/advanced-types.html#using-type-predicates) should be a viable alternative:
331
+
You can also use the `slice.action.myAction.match`[type predicate](https://www.typescriptlang.org/docs/handbook/advanced-types.html#using-type-predicates) should be a viable alternative:
// `action` is narrowed down to the type `PayloadAction<number>` here.
@@ -408,6 +411,59 @@ type AtLeastOne<T extends Record<string, any>> = keyof T extends infer K
408
411
typeAtLeastOneUserField=AtLeastOne<User>
409
412
```
410
413
414
+
### Typing Async Thunks Inside `createSlice`
415
+
416
+
As of 2.0, `createSlice` allows [defining thunks inside of `reducers` using a callback syntax](../api/createSlice.mdx/#the-reducers-creator-callback-notation).
417
+
418
+
Typing for the `create.asyncThunk` method works in the same way as [`createAsyncThunk`](#createasyncthunk), with one key difference.
419
+
420
+
A type for `state` and/or `dispatch` _cannot_ be provided as part of the `ThunkApiConfig`, as this would cause circular types.
421
+
422
+
Instead, it is necessary to assert the type when needed - `getState() asRootState`. You may also include an explicit return type for the payload function as well, in order to break the circular type inference cycle.
If you need to reuse reducer logic, it is common to write ["higher-order reducers"](https://redux.js.org/recipes/structuring-reducers/reusing-reducer-logic#customizing-behavior-with-higher-order-reducers) that wrap a reducer function with additional common behavior. This can be done with `createSlice` as well, but due to the complexity of the types for `createSlice`, you have to use the `SliceCaseReducers` and `ValidateSliceCaseReducers` types in a very specific way.
0 commit comments