Skip to content

Commit 3805c81

Browse files
committed
Add workaround for partial payloads
1 parent f2ecd03 commit 3805c81

File tree

1 file changed

+17
-0
lines changed

1 file changed

+17
-0
lines changed

docs/usage/usage-with-typescript.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,23 @@ const usersSlice = createSlice({
427427

428428
Like the `builder` in `createReducer`, this `builder` also accepts `addMatcher` (see [typing `builder.matcher`](#typing-builderaddmatcher)) and `addDefaultCase`.
429429

430+
### Payload with All Optional Fields
431+
432+
If you try to supply a payload type where all fields are optional, like `PayloadAction<Partial<User>>` or `PayloadAction<{value?: string}>`, TS may not be able to infer the action type correctly.
433+
434+
You can work around this by [using a custom `AtLeastOne` utility type](https://github.com/reduxjs/redux-toolkit/issues/1423#issuecomment-902680573) to help ensure that at least one of the fields must be passed in:
435+
436+
```ts no-transpile
437+
type AtLeastOne<T extends Record<string, any>> = keyof T extends infer K
438+
? K extends string
439+
? Pick<T, K & keyof T> & Partial<T>
440+
: never
441+
: never
442+
443+
// Use this type instead of `Partial<MyPayloadType>`
444+
type AtLeastOneUserField = AtLeastOne<User>
445+
```
446+
430447
### Wrapping `createSlice`
431448
432449
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

Comments
 (0)