Skip to content

Commit c8daec5

Browse files
committed
Move type test to type-d file
1 parent 711c8b4 commit c8daec5

File tree

4 files changed

+113
-12
lines changed

4 files changed

+113
-12
lines changed

packages/toolkit/src/createSlice.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ interface ReducerHandlingContext<State> {
195195
actionCreators: Record<string, any>
196196
}
197197

198-
interface ReducerHandlingContextMethods<State> {
198+
export interface ReducerHandlingContextMethods<State> {
199199
/**
200200
* Adds a case reducer to handle a single action type.
201201
* @param actionCreator - Either a plain action type string, or an action creator generated by [`createAction`](./createAction) that can be used to determine the action type.
@@ -267,7 +267,7 @@ interface ReducerHandlingContextMethods<State> {
267267
getInitialState(): State
268268
}
269269

270-
interface ReducerDetails {
270+
export interface ReducerDetails {
271271
/** The key the reducer was defined under */
272272
reducerName: string
273273
/** The predefined action type, i.e. `${slice.name}/${reducerName}` */

packages/toolkit/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ export type {
8787
ReducerNamesOfType,
8888
ReducerCreatorEntry,
8989
ReducerCreator,
90+
ReducerDetails,
91+
ReducerHandlingContextMethods,
9092
SliceActionType,
9193
CaseReducerDefinition,
9294
PreparedCaseReducerDefinition,

packages/toolkit/src/tests/createSlice.test-d.ts

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,19 @@ import type {
88
ActionReducerMapBuilder,
99
AsyncThunk,
1010
CaseReducer,
11+
CreatorCaseReducers,
1112
PayloadAction,
1213
PayloadActionCreator,
1314
Reducer,
15+
ReducerCreator,
16+
ReducerCreatorEntry,
1417
ReducerCreators,
1518
ReducerDefinition,
19+
ReducerHandlingContextMethods,
20+
ReducerNamesOfType,
1621
SerializedError,
1722
SliceCaseReducers,
23+
ThunkAction,
1824
ThunkDispatch,
1925
UnknownAction,
2026
ValidateSliceCaseReducers,
@@ -27,9 +33,12 @@ import {
2733
createAsyncThunk,
2834
createSlice,
2935
isRejected,
36+
nanoid,
3037
} from '@reduxjs/toolkit'
3138
import { castDraft } from 'immer'
3239

40+
const toasterCreatorType = Symbol()
41+
3342
describe('type tests', () => {
3443
const counterSlice = createSlice({
3544
name: 'counter',
@@ -983,4 +992,104 @@ describe('type tests', () => {
983992
},
984993
})
985994
})
995+
test('creators can disable themselves if state is incompatible', () => {
996+
const toastCreator: ReducerCreator<typeof toasterCreatorType> = {
997+
type: toasterCreatorType,
998+
create: () => ({
999+
_reducerDefinitionType: toasterCreatorType,
1000+
}),
1001+
handle({ type, reducerName }, _definition, context) {
1002+
const toastOpened = createAction<{ message: string; id: string }>(
1003+
type + '/opened',
1004+
)
1005+
const toastClosed = createAction<string>(type + '/closed')
1006+
function openToast(
1007+
ms: number,
1008+
message: string,
1009+
): ThunkAction<void, unknown, unknown, UnknownAction> {
1010+
return (dispatch, getState) => {
1011+
const id = nanoid()
1012+
dispatch(toastOpened({ message, id }))
1013+
setTimeout(() => {
1014+
dispatch(toastClosed(id))
1015+
}, ms)
1016+
}
1017+
}
1018+
Object.assign(openToast, { toastOpened, toastClosed })
1019+
;(context as ReducerHandlingContextMethods<ToastState>)
1020+
.addCase(toastOpened, (state, { payload: { message, id } }) => {
1021+
state.toasts[id] = { message }
1022+
})
1023+
.addCase(toastClosed, (state, action) => {
1024+
delete state.toasts[action.payload]
1025+
})
1026+
.exposeAction(reducerName, openToast)
1027+
},
1028+
}
1029+
1030+
const createAppSlice = buildCreateSlice({
1031+
creators: { toaster: toastCreator },
1032+
})
1033+
1034+
const toastSlice = createAppSlice({
1035+
name: 'toast',
1036+
initialState: { toasts: {} } as ToastState,
1037+
reducers: (create) => ({
1038+
toast: create.toaster(),
1039+
}),
1040+
})
1041+
1042+
expectTypeOf(toastSlice.actions.toast).toEqualTypeOf<AddToastThunk>()
1043+
1044+
expectTypeOf(toastSlice.actions.toast).toBeCallableWith(100, 'hello')
1045+
1046+
const incompatibleSlice = createAppSlice({
1047+
name: 'incompatible',
1048+
initialState: {},
1049+
reducers: (create) => {
1050+
expectTypeOf(create).not.toHaveProperty('toaster')
1051+
return {}
1052+
},
1053+
})
1054+
})
9861055
})
1056+
1057+
interface Toast {
1058+
message: string
1059+
}
1060+
1061+
interface ToastState {
1062+
toasts: Record<string, Toast>
1063+
}
1064+
1065+
interface AddToastThunk {
1066+
(
1067+
ms: number,
1068+
message: string,
1069+
): ThunkAction<void, unknown, unknown, UnknownAction>
1070+
toastOpened: PayloadActionCreator<{ message: string; id: string }>
1071+
toastClosed: PayloadActionCreator<string>
1072+
}
1073+
1074+
declare module '@reduxjs/toolkit' {
1075+
export interface SliceReducerCreators<
1076+
State = any,
1077+
CaseReducers extends
1078+
CreatorCaseReducers<State> = CreatorCaseReducers<State>,
1079+
Name extends string = string,
1080+
> {
1081+
[toasterCreatorType]: ReducerCreatorEntry<
1082+
State extends ToastState
1083+
? () => ReducerDefinition<typeof toasterCreatorType>
1084+
: never,
1085+
{
1086+
actions: {
1087+
[ReducerName in ReducerNamesOfType<
1088+
CaseReducers,
1089+
typeof toasterCreatorType
1090+
>]: AddToastThunk
1091+
}
1092+
}
1093+
>
1094+
}
1095+
}

packages/toolkit/src/tests/createSlice.test.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,16 +1200,6 @@ describe('createSlice', () => {
12001200
store.dispatch(reset())
12011201
expect(selectValue(store.getState())).toBe(1)
12021202
})
1203-
test.skip('creators can discourage their use if state is incompatible (types only)', () => {
1204-
const counterSlice = createAppSlice({
1205-
name: 'counter',
1206-
initialState: { value: 0 },
1207-
reducers: (create) => ({
1208-
// @ts-expect-error incompatible state
1209-
...create.historyMethods(),
1210-
}),
1211-
})
1212-
})
12131203
})
12141204
})
12151205
})

0 commit comments

Comments
 (0)