Skip to content

Commit 09cc0c7

Browse files
committed
split type test
1 parent a53a0c6 commit 09cc0c7

File tree

2 files changed

+265
-227
lines changed

2 files changed

+265
-227
lines changed
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
import type {
2+
ThunkDispatch,
3+
SerializedError,
4+
AsyncThunk,
5+
CaseReducer,
6+
} from '@reduxjs/toolkit'
7+
import {
8+
asyncThunkCreator,
9+
buildCreateSlice,
10+
isRejected,
11+
configureStore,
12+
} from '@reduxjs/toolkit'
13+
14+
describe('type tests', () => {
15+
test('reducer callback', () => {
16+
interface TestState {
17+
foo: string
18+
}
19+
20+
interface TestArg {
21+
test: string
22+
}
23+
24+
interface TestReturned {
25+
payload: string
26+
}
27+
28+
interface TestReject {
29+
cause: string
30+
}
31+
32+
const createAppSlice = buildCreateSlice({
33+
creators: { asyncThunk: asyncThunkCreator },
34+
})
35+
36+
const slice = createAppSlice({
37+
name: 'test',
38+
initialState: {} as TestState,
39+
reducers: (create) => {
40+
const preTypedAsyncThunk = create.asyncThunk.withTypes<{
41+
rejectValue: TestReject
42+
}>()
43+
44+
// @ts-expect-error
45+
create.asyncThunk<any, any, { state: StoreState }>(() => {})
46+
47+
// @ts-expect-error
48+
create.asyncThunk.withTypes<{
49+
rejectValue: string
50+
dispatch: StoreDispatch
51+
}>()
52+
53+
return {
54+
testInfer: create.asyncThunk(
55+
function payloadCreator(arg: TestArg, api) {
56+
return Promise.resolve<TestReturned>({ payload: 'foo' })
57+
},
58+
{
59+
pending(state, action) {
60+
expectTypeOf(state).toEqualTypeOf<TestState>()
61+
62+
expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
63+
},
64+
fulfilled(state, action) {
65+
expectTypeOf(state).toEqualTypeOf<TestState>()
66+
67+
expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
68+
69+
expectTypeOf(action.payload).toEqualTypeOf<TestReturned>()
70+
},
71+
rejected(state, action) {
72+
expectTypeOf(state).toEqualTypeOf<TestState>()
73+
74+
expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
75+
76+
expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
77+
},
78+
settled(state, action) {
79+
expectTypeOf(state).toEqualTypeOf<TestState>()
80+
81+
expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
82+
83+
if (isRejected(action)) {
84+
expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
85+
} else {
86+
expectTypeOf(action.payload).toEqualTypeOf<TestReturned>()
87+
}
88+
},
89+
},
90+
),
91+
testExplicitType: create.asyncThunk<
92+
TestReturned,
93+
TestArg,
94+
{
95+
rejectValue: TestReject
96+
}
97+
>(
98+
function payloadCreator(arg, api) {
99+
// here would be a circular reference
100+
expectTypeOf(api.getState()).toBeUnknown()
101+
// here would be a circular reference
102+
expectTypeOf(api.dispatch).toMatchTypeOf<
103+
ThunkDispatch<any, any, any>
104+
>()
105+
106+
// so you need to cast inside instead
107+
const getState = api.getState as () => StoreState
108+
const dispatch = api.dispatch as StoreDispatch
109+
110+
expectTypeOf(arg).toEqualTypeOf<TestArg>()
111+
112+
expectTypeOf(api.rejectWithValue).toMatchTypeOf<
113+
(value: TestReject) => any
114+
>()
115+
116+
return Promise.resolve({ payload: 'foo' })
117+
},
118+
{
119+
pending(state, action) {
120+
expectTypeOf(state).toEqualTypeOf<TestState>()
121+
122+
expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
123+
},
124+
fulfilled(state, action) {
125+
expectTypeOf(state).toEqualTypeOf<TestState>()
126+
127+
expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
128+
129+
expectTypeOf(action.payload).toEqualTypeOf<TestReturned>()
130+
},
131+
rejected(state, action) {
132+
expectTypeOf(state).toEqualTypeOf<TestState>()
133+
134+
expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
135+
136+
expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
137+
138+
expectTypeOf(action.payload).toEqualTypeOf<
139+
TestReject | undefined
140+
>()
141+
},
142+
settled(state, action) {
143+
expectTypeOf(state).toEqualTypeOf<TestState>()
144+
145+
expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
146+
147+
if (isRejected(action)) {
148+
expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
149+
150+
expectTypeOf(action.payload).toEqualTypeOf<
151+
TestReject | undefined
152+
>()
153+
} else {
154+
expectTypeOf(action.payload).toEqualTypeOf<TestReturned>()
155+
}
156+
},
157+
},
158+
),
159+
testPreTyped: preTypedAsyncThunk(
160+
function payloadCreator(arg: TestArg, api) {
161+
expectTypeOf(api.rejectWithValue).toMatchTypeOf<
162+
(value: TestReject) => any
163+
>()
164+
165+
return Promise.resolve<TestReturned>({ payload: 'foo' })
166+
},
167+
{
168+
pending(state, action) {
169+
expectTypeOf(state).toEqualTypeOf<TestState>()
170+
171+
expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
172+
},
173+
fulfilled(state, action) {
174+
expectTypeOf(state).toEqualTypeOf<TestState>()
175+
176+
expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
177+
178+
expectTypeOf(action.payload).toEqualTypeOf<TestReturned>()
179+
},
180+
rejected(state, action) {
181+
expectTypeOf(state).toEqualTypeOf<TestState>()
182+
183+
expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
184+
185+
expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
186+
187+
expectTypeOf(action.payload).toEqualTypeOf<
188+
TestReject | undefined
189+
>()
190+
},
191+
settled(state, action) {
192+
expectTypeOf(state).toEqualTypeOf<TestState>()
193+
194+
expectTypeOf(action.meta.arg).toEqualTypeOf<TestArg>()
195+
196+
if (isRejected(action)) {
197+
expectTypeOf(action.error).toEqualTypeOf<SerializedError>()
198+
199+
expectTypeOf(action.payload).toEqualTypeOf<
200+
TestReject | undefined
201+
>()
202+
} else {
203+
expectTypeOf(action.payload).toEqualTypeOf<TestReturned>()
204+
}
205+
},
206+
},
207+
),
208+
}
209+
},
210+
})
211+
212+
const store = configureStore({ reducer: { test: slice.reducer } })
213+
214+
type StoreState = ReturnType<typeof store.getState>
215+
216+
type StoreDispatch = typeof store.dispatch
217+
218+
expectTypeOf(slice.actions.testInfer).toEqualTypeOf<
219+
AsyncThunk<TestReturned, TestArg, {}>
220+
>()
221+
222+
expectTypeOf(slice.actions.testExplicitType).toEqualTypeOf<
223+
AsyncThunk<TestReturned, TestArg, { rejectValue: TestReject }>
224+
>()
225+
226+
type TestInferThunk = AsyncThunk<TestReturned, TestArg, {}>
227+
228+
expectTypeOf(slice.caseReducers.testInfer.pending).toEqualTypeOf<
229+
CaseReducer<TestState, ReturnType<TestInferThunk['pending']>>
230+
>()
231+
232+
expectTypeOf(slice.caseReducers.testInfer.fulfilled).toEqualTypeOf<
233+
CaseReducer<TestState, ReturnType<TestInferThunk['fulfilled']>>
234+
>()
235+
236+
expectTypeOf(slice.caseReducers.testInfer.rejected).toEqualTypeOf<
237+
CaseReducer<TestState, ReturnType<TestInferThunk['rejected']>>
238+
>()
239+
})
240+
})

0 commit comments

Comments
 (0)