@@ -190,7 +190,11 @@ interface InternalReducerHandlingContext<State> {
190190 actionCreators : Record < string , any >
191191}
192192
193- export interface ReducerHandlingContext < State > {
193+ export interface ReducerHandlingContext <
194+ State ,
195+ Name extends string ,
196+ ReducerPath extends string ,
197+ > {
194198 /**
195199 * Adds a case reducer to handle a single action type.
196200 * @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.
@@ -199,7 +203,7 @@ export interface ReducerHandlingContext<State> {
199203 addCase < ActionCreator extends TypedActionCreator < string > > (
200204 actionCreator : ActionCreator ,
201205 reducer : CaseReducer < State , ReturnType < ActionCreator > > ,
202- ) : ReducerHandlingContext < State >
206+ ) : ReducerHandlingContext < State , Name , ReducerPath >
203207 /**
204208 * Adds a case reducer to handle a single action type.
205209 * @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.
@@ -208,7 +212,7 @@ export interface ReducerHandlingContext<State> {
208212 addCase < Type extends string , A extends Action < Type > > (
209213 type : Type ,
210214 reducer : CaseReducer < State , A > ,
211- ) : ReducerHandlingContext < State >
215+ ) : ReducerHandlingContext < State , Name , ReducerPath >
212216
213217 /**
214218 * Allows you to match incoming actions against your own filter function instead of only the `action.type` property.
@@ -224,7 +228,7 @@ export interface ReducerHandlingContext<State> {
224228 addMatcher < A > (
225229 matcher : TypeGuard < A > ,
226230 reducer : CaseReducer < State , A extends Action ? A : A & Action > ,
227- ) : ReducerHandlingContext < State >
231+ ) : ReducerHandlingContext < State , Name , ReducerPath >
228232 /**
229233 * Add an action to be exposed under the final `slice.actions[reducerName]` key.
230234 *
@@ -238,7 +242,10 @@ export interface ReducerHandlingContext<State> {
238242 *
239243 * dispatch(addPost(post))
240244 */
241- exposeAction ( actionCreator : unknown ) : ReducerHandlingContext < State >
245+ exposeAction (
246+ actionCreator : unknown ,
247+ ) : ReducerHandlingContext < State , Name , ReducerPath >
248+
242249 /**
243250 * Add a case reducer to be exposed under the final `slice.caseReducers[reducerName]` key.
244251 *
@@ -252,12 +259,34 @@ export interface ReducerHandlingContext<State> {
252259 *
253260 * slice.caseReducers.addPost([], addPost(post))
254261 */
255- exposeCaseReducer ( reducer : unknown ) : ReducerHandlingContext < State >
262+ exposeCaseReducer (
263+ reducer : unknown ,
264+ ) : ReducerHandlingContext < State , Name , ReducerPath >
265+
256266 /**
257267 * Provides access to the initial state value given to the slice.
258268 * If a lazy state initializer was provided, it will be called and a fresh value returned.
259269 */
260270 getInitialState ( ) : State
271+
272+ /**
273+ * The `name` option provided for the slice.
274+ */
275+ name : Name
276+
277+ /**
278+ * The `reducerPath` option provided for the slice.
279+ * Defaults to `name` if not provided.
280+ */
281+ reducerPath : ReducerPath
282+
283+ /**
284+ * Tries to select the slice's state from a possible root state shape, using `reducerPath`.
285+ * Throws an error if slice's state is not found.
286+ *
287+ * *Note that only the original `reducerPath` option is used - if a different `reducerPath` is used when injecting, this will not be reflected.*
288+ */
289+ selectSlice ( state : Record < ReducerPath , State > ) : State
261290}
262291
263292export interface ReducerDetails {
@@ -314,10 +343,10 @@ export type ReducerCreator<Type extends RegisteredReducerType> = {
314343} & ( ReducerDefinitionsForType < Type > extends never
315344 ? { }
316345 : {
317- handle < State > (
346+ handle < State , Name extends string , ReducerPath extends string > (
318347 details : ReducerDetails ,
319348 definition : ReducerDefinitionsForType < Type > ,
320- context : ReducerHandlingContext < State > ,
349+ context : ReducerHandlingContext < State , Name , ReducerPath > ,
321350 ) : void
322351 } )
323352
@@ -388,7 +417,7 @@ export interface Slice<
388417 * Equivalent to `slice.getSelectors((state: RootState) => state[slice.reducerPath])`.
389418 */
390419 get selectors ( ) : Id <
391- SliceDefinedSelectors < State , Selectors , { [ K in ReducerPath ] : State } >
420+ SliceDefinedSelectors < State , Selectors , Record < ReducerPath , State > >
392421 >
393422
394423 /**
@@ -410,7 +439,7 @@ export interface Slice<
410439 *
411440 * Will throw an error if slice is not found.
412441 */
413- selectSlice ( state : { [ K in ReducerPath ] : State } ) : State
442+ selectSlice ( state : Record < ReducerPath , State > ) : State
414443}
415444
416445/**
@@ -898,7 +927,7 @@ export function buildCreateSlice<
898927 }
899928
900929 function getContext ( { reducerName } : ReducerDetails ) {
901- const context : ReducerHandlingContext < State > = {
930+ const context : ReducerHandlingContext < State , Name , ReducerPath > = {
902931 addCase (
903932 typeOrActionCreator : string | TypedActionCreator < any > ,
904933 reducer : CaseReducer < State > ,
@@ -946,6 +975,17 @@ export function buildCreateSlice<
946975 return context
947976 } ,
948977 getInitialState,
978+ name,
979+ reducerPath,
980+ selectSlice ( state ) {
981+ const sliceState = state [ reducerPath ]
982+ if ( typeof sliceState === 'undefined' ) {
983+ throw new Error (
984+ `Could not find "${ name } " slice in state. In order for slice creators to use \`context.selectSlice\`, the slice must be nested in the state under its reducerPath: "${ reducerPath } "` ,
985+ )
986+ }
987+ return sliceState
988+ } ,
949989 }
950990 return context
951991 }
0 commit comments