@@ -29,13 +29,30 @@ export interface SerializedError {
29
29
code ?: string
30
30
}
31
31
32
- const commonProperties : ( keyof SerializedError ) [ ] = [
32
+ const commonProperties : Array < keyof SerializedError > = [
33
33
'name' ,
34
34
'message' ,
35
35
'stack' ,
36
36
'code'
37
37
]
38
38
39
+ const rejectionSymbol : unique symbol = Symbol ( 'rejectWithValue' )
40
+ type RejectWithValue < RejectValue > = {
41
+ [ rejectionSymbol ] : 'reject'
42
+ value : RejectValue
43
+ }
44
+ function rejectWithValue < RejectValue > (
45
+ value : RejectValue
46
+ ) : RejectWithValue < RejectValue > {
47
+ return {
48
+ [ rejectionSymbol ] : 'reject' ,
49
+ value
50
+ }
51
+ }
52
+ function isRejectWithValue ( value : any ) : value is RejectWithValue < unknown > {
53
+ return value [ rejectionSymbol ] === 'reject'
54
+ }
55
+
39
56
// Reworked from https://github.com/sindresorhus/serialize-error
40
57
export const miniSerializeError = ( value : any ) : any => {
41
58
if ( typeof value === 'object' && value !== null ) {
@@ -56,6 +73,7 @@ type AsyncThunkConfig = {
56
73
state ?: unknown
57
74
dispatch ?: Dispatch
58
75
extra ?: unknown
76
+ rejectValue ?: unknown
59
77
}
60
78
61
79
type GetState < ThunkApiConfig > = ThunkApiConfig extends {
@@ -84,6 +102,11 @@ type GetThunkAPI<ThunkApiConfig> = BaseThunkAPI<
84
102
GetExtra < ThunkApiConfig > ,
85
103
GetDispatch < ThunkApiConfig >
86
104
>
105
+ type GetRejectValue < ThunkApiConfig > = ThunkApiConfig extends {
106
+ rejectValue : infer RejectValue
107
+ }
108
+ ? RejectValue
109
+ : undefined
87
110
88
111
/**
89
112
*
@@ -101,8 +124,14 @@ export function createAsyncThunk<
101
124
payloadCreator : (
102
125
arg : ThunkArg ,
103
126
thunkAPI : GetThunkAPI < ThunkApiConfig >
104
- ) => Promise < Returned > | Returned
127
+ ) =>
128
+ | Promise < Returned >
129
+ | Returned
130
+ | Promise < RejectWithValue < GetRejectValue < ThunkApiConfig > > >
131
+ | RejectWithValue < GetRejectValue < ThunkApiConfig > >
105
132
) {
133
+ type RejectedValue = GetRejectValue < ThunkApiConfig >
134
+
106
135
const fulfilled = createAction (
107
136
type + '/fulfilled' ,
108
137
( result : Returned , requestId : string , arg : ThunkArg ) => {
@@ -125,10 +154,15 @@ export function createAsyncThunk<
125
154
126
155
const rejected = createAction (
127
156
type + '/rejected' ,
128
- ( error : Error , requestId : string , arg : ThunkArg ) => {
157
+ (
158
+ error : Error | null ,
159
+ requestId : string ,
160
+ arg : ThunkArg ,
161
+ payload ?: RejectedValue
162
+ ) => {
129
163
const aborted = error && error . name === 'AbortError'
130
164
return {
131
- payload : undefined ,
165
+ payload,
132
166
error : miniSerializeError ( error ) ,
133
167
meta : {
134
168
arg,
@@ -175,7 +209,12 @@ export function createAsyncThunk<
175
209
requestId,
176
210
signal : abortController . signal
177
211
} )
178
- ) . then ( result => fulfilled ( result , requestId , arg ) )
212
+ ) . then ( result => {
213
+ if ( isRejectWithValue ( result ) ) {
214
+ return rejected ( null , requestId , arg , result . value )
215
+ }
216
+ return fulfilled ( result , requestId , arg )
217
+ } )
179
218
] )
180
219
} catch ( err ) {
181
220
finalAction = rejected ( err , requestId , arg )
@@ -198,6 +237,7 @@ export function createAsyncThunk<
198
237
fulfilled
199
238
} )
200
239
}
240
+ createAsyncThunk . rejectWithValue = rejectWithValue
201
241
202
242
/**
203
243
* @alpha
0 commit comments