UNPKG

3.53 kBPlain TextView Raw
1import type {
2 EntityAdapter,
3 ActionCreatorWithPayload,
4 ActionCreatorWithoutPayload,
5 EntityStateAdapter,
6 EntityId,
7 Update,
8} from '@reduxjs/toolkit'
9import { createSlice, createEntityAdapter } from '@reduxjs/toolkit'
10import { expectType } from './helpers'
11
12function extractReducers<T>(
13 adapter: EntityAdapter<T>
14): Omit<EntityStateAdapter<T>, 'map'> {
15 const { selectId, sortComparer, getInitialState, getSelectors, ...rest } =
16 adapter
17 return rest
18}
19
20/**
21 * should be usable in a slice, with all the "reducer-like" functions
22 */
23{
24 type Entity = {
25 value: string
26 }
27 const adapter = createEntityAdapter<Entity>()
28 const slice = createSlice({
29 name: 'test',
30 initialState: adapter.getInitialState(),
31 reducers: {
32 ...extractReducers(adapter),
33 },
34 })
35
36 expectType<ActionCreatorWithPayload<Entity>>(slice.actions.addOne)
37 expectType<
38 ActionCreatorWithPayload<ReadonlyArray<Entity> | Record<string, Entity>>
39 >(slice.actions.addMany)
40 expectType<
41 ActionCreatorWithPayload<ReadonlyArray<Entity> | Record<string, Entity>>
42 >(slice.actions.setAll)
43 expectType<ActionCreatorWithPayload<Entity[] | Record<string, Entity>>>(
44 // @ts-expect-error
45 slice.actions.addMany
46 )
47 expectType<ActionCreatorWithPayload<Entity[] | Record<string, Entity>>>(
48 // @ts-expect-error
49 slice.actions.setAll
50 )
51 expectType<ActionCreatorWithPayload<EntityId>>(slice.actions.removeOne)
52 expectType<ActionCreatorWithPayload<ReadonlyArray<EntityId>>>(
53 slice.actions.removeMany
54 )
55 // @ts-expect-error
56 expectType<ActionCreatorWithPayload<EntityId[]>>(slice.actions.removeMany)
57 expectType<ActionCreatorWithoutPayload>(slice.actions.removeAll)
58 expectType<ActionCreatorWithPayload<Update<Entity>>>(slice.actions.updateOne)
59 expectType<ActionCreatorWithPayload<Update<Entity>[]>>(
60 // @ts-expect-error
61 slice.actions.updateMany
62 )
63 expectType<ActionCreatorWithPayload<ReadonlyArray<Update<Entity>>>>(
64 slice.actions.updateMany
65 )
66 expectType<ActionCreatorWithPayload<Entity>>(slice.actions.upsertOne)
67 expectType<
68 ActionCreatorWithPayload<ReadonlyArray<Entity> | Record<string, Entity>>
69 >(slice.actions.upsertMany)
70 expectType<ActionCreatorWithPayload<Entity[] | Record<string, Entity>>>(
71 // @ts-expect-error
72 slice.actions.upsertMany
73 )
74}
75
76/**
77 * should not be able to mix with a different EntityAdapter
78 */
79{
80 type Entity = {
81 value: string
82 }
83 type Entity2 = {
84 value2: string
85 }
86 const adapter = createEntityAdapter<Entity>()
87 const adapter2 = createEntityAdapter<Entity2>()
88 createSlice({
89 name: 'test',
90 initialState: adapter.getInitialState(),
91 reducers: {
92 addOne: adapter.addOne,
93 // @ts-expect-error
94 addOne2: adapter2.addOne,
95 },
96 })
97}
98
99/**
100 * should be usable in a slice with extra properties
101 */
102{
103 type Entity = {
104 value: string
105 }
106 const adapter = createEntityAdapter<Entity>()
107 createSlice({
108 name: 'test',
109 initialState: adapter.getInitialState({ extraData: 'test' }),
110 reducers: {
111 addOne: adapter.addOne,
112 },
113 })
114}
115
116/**
117 * should not be usable in a slice with an unfitting state
118 */
119{
120 type Entity = {
121 value: string
122 }
123 const adapter = createEntityAdapter<Entity>()
124 createSlice({
125 name: 'test',
126 initialState: { somethingElse: '' },
127 reducers: {
128 // @ts-expect-error
129 addOne: adapter.addOne,
130 },
131 })
132}