1- import type { Reducer , StateFromReducersMapObject , UnknownAction } from 'redux'
1+ import type {
2+ PreloadedStateShapeFromReducersMapObject ,
3+ Reducer ,
4+ StateFromReducersMapObject ,
5+ UnknownAction ,
6+ } from 'redux'
27import { combineReducers } from 'redux'
38import { nanoid } from './nanoid'
49import type {
@@ -10,9 +15,9 @@ import type {
1015} from './tsHelpers'
1116import { getOrInsertComputed } from './utils'
1217
13- type SliceLike < ReducerPath extends string , State > = {
18+ type SliceLike < ReducerPath extends string , State , PreloadedState = State > = {
1419 reducerPath : ReducerPath
15- reducer : Reducer < State >
20+ reducer : Reducer < State , any , PreloadedState >
1621}
1722
1823type AnySliceLike = SliceLike < string , any >
@@ -21,18 +26,26 @@ type SliceLikeReducerPath<A extends AnySliceLike> =
2126 A extends SliceLike < infer ReducerPath , any > ? ReducerPath : never
2227
2328type SliceLikeState < A extends AnySliceLike > =
24- A extends SliceLike < any , infer State > ? State : never
29+ A extends SliceLike < any , infer State , any > ? State : never
30+
31+ type SliceLikePreloadedState < A extends AnySliceLike > =
32+ A extends SliceLike < any , any , infer PreloadedState > ? PreloadedState : never
2533
2634export type WithSlice < A extends AnySliceLike > = {
2735 [ Path in SliceLikeReducerPath < A > ] : SliceLikeState < A >
2836}
2937
38+ export type WithSlicePreloadedState < A extends AnySliceLike > = {
39+ [ Path in SliceLikeReducerPath < A > ] : SliceLikePreloadedState < A >
40+ }
41+
3042type ReducerMap = Record < string , Reducer >
3143
32- type ExistingSliceLike < DeclaredState > = {
44+ type ExistingSliceLike < DeclaredState , PreloadedState > = {
3345 [ ReducerPath in keyof DeclaredState ] : SliceLike <
3446 ReducerPath & string ,
35- NonUndefined < DeclaredState [ ReducerPath ] >
47+ NonUndefined < DeclaredState [ ReducerPath ] > ,
48+ NonUndefined < PreloadedState [ ReducerPath & keyof PreloadedState ] >
3649 >
3750} [ keyof DeclaredState ]
3851
@@ -48,8 +61,11 @@ export type InjectConfig = {
4861 */
4962export interface CombinedSliceReducer <
5063 InitialState ,
51- DeclaredState = InitialState ,
52- > extends Reducer < DeclaredState , UnknownAction , Partial < DeclaredState > > {
64+ DeclaredState extends InitialState = InitialState ,
65+ PreloadedState extends Partial <
66+ Record < keyof PreloadedState , any >
67+ > = Partial < DeclaredState > ,
68+ > extends Reducer < DeclaredState , UnknownAction , PreloadedState > {
5369 /**
5470 * Provide a type for slices that will be injected lazily.
5571 *
@@ -79,9 +95,10 @@ export interface CombinedSliceReducer<
7995 * const withCustom = rootReducer.inject({ reducerPath: "customName", reducer: customSlice.reducer })
8096 * ```
8197 */
82- withLazyLoadedSlices < Lazy = { } > ( ) : CombinedSliceReducer <
98+ withLazyLoadedSlices < Lazy = { } , LazyPreloaded = Lazy > ( ) : CombinedSliceReducer <
8399 InitialState ,
84- Id < DeclaredState & Partial < Lazy > >
100+ Id < DeclaredState & Partial < Lazy > > ,
101+ Id < PreloadedState & Partial < LazyPreloaded > >
85102 >
86103
87104 /**
@@ -96,10 +113,14 @@ export interface CombinedSliceReducer<
96113 * ```
97114 *
98115 */
99- inject < Sl extends Id < ExistingSliceLike < DeclaredState > > > (
116+ inject < Sl extends Id < ExistingSliceLike < DeclaredState , PreloadedState > > > (
100117 slice : Sl ,
101118 config ?: InjectConfig ,
102- ) : CombinedSliceReducer < InitialState , Id < DeclaredState & WithSlice < Sl > > >
119+ ) : CombinedSliceReducer <
120+ InitialState ,
121+ Id < DeclaredState & WithSlice < Sl > > ,
122+ Id < PreloadedState & Partial < WithSlicePreloadedState < Sl > > >
123+ >
103124
104125 /**
105126 * Inject a slice.
@@ -113,15 +134,21 @@ export interface CombinedSliceReducer<
113134 * ```
114135 *
115136 */
116- inject < ReducerPath extends string , State > (
137+ inject < ReducerPath extends string , State , PreloadedState = State > (
117138 slice : SliceLike <
118139 ReducerPath ,
119- State & ( ReducerPath extends keyof DeclaredState ? never : State )
140+ State & ( ReducerPath extends keyof DeclaredState ? never : State ) ,
141+ PreloadedState &
142+ ( ReducerPath extends keyof PreloadedState ? never : PreloadedState )
120143 > ,
121144 config ?: InjectConfig ,
122145 ) : CombinedSliceReducer <
123146 InitialState ,
124- Id < DeclaredState & WithSlice < SliceLike < ReducerPath , State > > >
147+ Id < DeclaredState & WithSlice < SliceLike < ReducerPath , State > > > ,
148+ Id <
149+ PreloadedState &
150+ WithSlicePreloadedState < SliceLike < ReducerPath , State , PreloadedState > >
151+ >
125152 >
126153
127154 /**
@@ -301,14 +328,23 @@ type InitialState<Slices extends Array<AnySliceLike | ReducerMap>> =
301328 : never
302329 >
303330
331+ type InitialPreloadedState < Slices extends Array < AnySliceLike | ReducerMap > > =
332+ UnionToIntersection <
333+ Slices [ number ] extends infer Slice
334+ ? Slice extends AnySliceLike
335+ ? WithSlicePreloadedState < Slice >
336+ : PreloadedStateShapeFromReducersMapObject < Slice >
337+ : never
338+ >
339+
304340const isSliceLike = (
305341 maybeSliceLike : AnySliceLike | ReducerMap ,
306342) : maybeSliceLike is AnySliceLike =>
307343 'reducerPath' in maybeSliceLike &&
308344 typeof maybeSliceLike . reducerPath === 'string'
309345
310346const getReducers = ( slices : Array < AnySliceLike | ReducerMap > ) =>
311- slices . flatMap ( ( sliceOrMap ) =>
347+ slices . flatMap < [ string , Reducer ] > ( ( sliceOrMap ) =>
312348 isSliceLike ( sliceOrMap )
313349 ? [ [ sliceOrMap . reducerPath , sliceOrMap . reducer ] as const ]
314350 : Object . entries ( sliceOrMap ) ,
@@ -370,7 +406,11 @@ const noopReducer: Reducer<Record<string, any>> = (state = emptyObject) => state
370406
371407export function combineSlices < Slices extends Array < AnySliceLike | ReducerMap > > (
372408 ...slices : Slices
373- ) : CombinedSliceReducer < Id < InitialState < Slices > > > {
409+ ) : CombinedSliceReducer <
410+ Id < InitialState < Slices > > ,
411+ Id < InitialState < Slices > > ,
412+ Partial < Id < InitialPreloadedState < Slices > > >
413+ > {
374414 const reducerMap = Object . fromEntries < Reducer > ( getReducers ( slices ) )
375415
376416 const getReducer = ( ) =>
0 commit comments