Skip to content

Commit 6770813

Browse files
authored
Merge pull request #4011 from reduxjs/nullable-state
Preserve nullable store state type by avoiding intersection with {}
2 parents 05b585f + cf7dd43 commit 6770813

File tree

5 files changed

+23
-8
lines changed

5 files changed

+23
-8
lines changed

packages/toolkit/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@
112112
],
113113
"dependencies": {
114114
"immer": "^10.0.3",
115-
"redux": "^5.0.0",
115+
"redux": "^5.0.1",
116116
"redux-thunk": "^3.1.0",
117117
"reselect": "^5.0.1"
118118
},

packages/toolkit/src/configureStore.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import type {
2626
ExtractDispatchExtensions,
2727
ExtractStoreExtensions,
2828
ExtractStateExtensions,
29+
UnknownIfNonSpecific,
2930
} from './tsHelpers'
3031
import type { Tuple } from './utils'
3132
import type { GetDefaultEnhancers } from './getDefaultEnhancers'
@@ -103,7 +104,8 @@ export type EnhancedStore<
103104
S = any,
104105
A extends Action = UnknownAction,
105106
E extends Enhancers = Enhancers
106-
> = ExtractStoreExtensions<E> & Store<S & ExtractStateExtensions<E>, A>
107+
> = ExtractStoreExtensions<E> &
108+
Store<S, A, UnknownIfNonSpecific<ExtractStateExtensions<E>>>
107109

108110
/**
109111
* A friendly abstraction over the standard Redux `createStore()` function.

packages/toolkit/src/tests/configureStore.typetest.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import type { PayloadAction, ConfigureStoreOptions } from '@reduxjs/toolkit'
1313
import { configureStore, createSlice, Tuple } from '@reduxjs/toolkit'
1414
import type { ThunkMiddleware, ThunkAction, ThunkDispatch } from 'redux-thunk'
1515
import { thunk } from 'redux-thunk'
16-
import { expectNotAny, expectType } from './helpers'
16+
import { expectExactType, expectNotAny, expectType } from './helpers'
1717

1818
const _anyMiddleware: any = () => () => () => {}
1919

@@ -138,6 +138,17 @@ const _anyMiddleware: any = () => () => () => {}
138138
})
139139
}
140140

141+
/**
142+
* Test: nullable state is preserved
143+
*/
144+
145+
{
146+
const store = configureStore({
147+
reducer: (): string | null => null,
148+
})
149+
expectExactType<string | null>(null)(store.getState())
150+
}
151+
141152
/*
142153
* Test: configureStore() accepts store Tuple, but not plain array
143154
*/

packages/toolkit/src/tsHelpers.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,3 +205,5 @@ export type Id<T> = { [K in keyof T]: T[K] } & {}
205205
export type Tail<T extends any[]> = T extends [any, ...infer Tail]
206206
? Tail
207207
: never
208+
209+
export type UnknownIfNonSpecific<T> = {} extends T ? unknown : T

yarn.lock

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7075,7 +7075,7 @@ __metadata:
70757075
node-fetch: ^2.6.1
70767076
prettier: ^2.2.1
70777077
query-string: ^7.0.1
7078-
redux: ^5.0.0
7078+
redux: ^5.0.1
70797079
redux-thunk: ^3.1.0
70807080
reselect: ^5.0.1
70817081
rimraf: ^3.0.2
@@ -25152,10 +25152,10 @@ fsevents@^1.2.7:
2515225152
languageName: node
2515325153
linkType: hard
2515425154

25155-
"redux@npm:^5.0.0":
25156-
version: 5.0.0
25157-
resolution: "redux@npm:5.0.0"
25158-
checksum: be49160d4bd01e10108c425ade999f1b456204895c4bdd0c7825ab09efffded51955c5c242847406a7b3f273e9011a9c102848c512a099a75617b97b13d2cca8
25155+
"redux@npm:^5.0.1":
25156+
version: 5.0.1
25157+
resolution: "redux@npm:5.0.1"
25158+
checksum: e74affa9009dd5d994878b9a1ce30d6569d986117175056edb003de2651c05b10fe7819d6fa94aea1a94de9a82f252f986547f007a2fbeb35c317a2e5f5ecf2c
2515925159
languageName: node
2516025160
linkType: hard
2516125161

0 commit comments

Comments
 (0)