1
1
import { Dispatch } from 'redux'
2
2
import { createAction } from './createAction'
3
3
4
- export type Await < T > = T extends {
5
- then ( onfulfilled ?: ( value : infer U ) => unknown ) : unknown
6
- }
7
- ? U
8
- : T
9
-
10
- export interface AsyncThunkParams <
11
- A ,
12
- D extends Dispatch ,
13
- S extends unknown ,
14
- E extends unknown
15
- > {
16
- args : A
4
+ type AsyncThunksArgs < S , E , D extends Dispatch = Dispatch > = {
17
5
dispatch : D
18
- getState : ( ) => S
6
+ getState : S
19
7
extra : E
20
8
}
21
9
22
- export type AsyncActionCreator <
23
- A ,
24
- D extends Dispatch ,
25
- S extends unknown ,
26
- E extends unknown
27
- > = ( params : AsyncThunkParams < A , D , S , E > ) => any
28
-
29
10
/**
30
11
*
31
12
* @param type
@@ -35,19 +16,23 @@ export type AsyncActionCreator<
35
16
*/
36
17
export function createAsyncThunk <
37
18
ActionType extends string ,
38
- PayloadCreator extends AsyncActionCreator <
19
+ Returned ,
20
+ ActionParams = never ,
21
+ TA extends AsyncThunksArgs < any , any , any > = AsyncThunksArgs <
39
22
unknown ,
40
- Dispatch ,
41
23
unknown ,
42
- undefined
24
+ Dispatch
43
25
>
44
- > ( type : ActionType , payloadCreator : PayloadCreator ) {
45
- // TODO This results in some hideous-looking inferred types for the actions
46
- type ActionParams = Parameters < PayloadCreator > [ 0 ] [ 'args' ]
47
-
26
+ > (
27
+ type : ActionType ,
28
+ payloadCreator : (
29
+ args : ActionParams ,
30
+ thunkArgs : TA
31
+ ) => Promise < Returned > | Returned
32
+ ) {
48
33
const fulfilled = createAction (
49
34
type + '/fulfilled' ,
50
- ( result : Await < ReturnType < PayloadCreator > > , args : ActionParams ) => {
35
+ ( result : Returned , args : ActionParams ) => {
51
36
return {
52
37
payload : result ,
53
38
meta : { args }
@@ -80,17 +65,20 @@ export function createAsyncThunk<
80
65
}
81
66
)
82
67
83
- function actionCreator ( args ?: ActionParams ) {
84
- return async ( dispatch : any , getState : any , extra : any ) => {
68
+ function actionCreator ( args : ActionParams ) {
69
+ return async (
70
+ dispatch : TA [ 'dispatch' ] ,
71
+ getState : TA [ 'getState' ] ,
72
+ extra : TA [ 'extra' ]
73
+ ) => {
85
74
try {
86
75
dispatch ( pending ( args ) )
87
76
// TODO Also ugly types
88
- const result : Await < ReturnType < PayloadCreator > > = await payloadCreator ( {
89
- args,
77
+ const result = ( await payloadCreator ( args , {
90
78
dispatch,
91
79
getState,
92
80
extra
93
- } )
81
+ } as TA ) ) as Returned
94
82
95
83
// TODO How do we avoid errors in here from hitting the catch clause?
96
84
return dispatch ( fulfilled ( result , args ) )
0 commit comments