Skip to content

Commit 00258ca

Browse files
committed
Revert unnecessary changes
1 parent 4439c31 commit 00258ca

File tree

6 files changed

+107
-53
lines changed

6 files changed

+107
-53
lines changed

src/applyMiddleware.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ export default function applyMiddleware<Ext, S = any>(
5454
): StoreEnhancer<{ dispatch: Ext }>
5555
export default function applyMiddleware(
5656
...middlewares: Middleware[]
57-
): StoreEnhancer {
57+
): StoreEnhancer<any> {
5858
return (createStore: StoreCreator) => <S, A extends AnyAction>(
5959
reducer: Reducer<S, A>,
6060
...args: any[]

src/createStore.ts

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import {
55
PreloadedState,
66
StoreEnhancer,
77
Dispatch,
8-
Observer
8+
Observer,
9+
ExtendState
910
} from './types/store'
1011
import { Action } from './types/actions'
1112
import { Reducer } from './types/reducers'
@@ -37,20 +38,31 @@ import isPlainObject from './utils/isPlainObject'
3738
* @returns A Redux store that lets you read the state, dispatch actions
3839
* and subscribe to changes.
3940
*/
40-
export default function createStore<S, A extends Action>(
41+
export default function createStore<
42+
S,
43+
A extends Action,
44+
Ext = {},
45+
StateExt = never
46+
>(
4147
reducer: Reducer<S, A>,
42-
preloadedState?: PreloadedState<S>
43-
): Store<S, A>
44-
export default function createStore<S, A extends Action, Ext, StateExt>(
45-
reducer: Reducer<S, A>,
46-
enhancer: StoreEnhancer<Ext, StateExt>
48+
enhancer?: StoreEnhancer<Ext, StateExt>
4749
): Store<S, A, StateExt> & Ext
48-
export default function createStore<S, A extends Action, Ext, StateExt>(
50+
export default function createStore<
51+
S,
52+
A extends Action,
53+
Ext = {},
54+
StateExt = never
55+
>(
4956
reducer: Reducer<S, A>,
50-
preloadedState: PreloadedState<S>,
51-
enhancer: StoreEnhancer<Ext, StateExt>
57+
preloadedState?: PreloadedState<S>,
58+
enhancer?: StoreEnhancer<Ext, StateExt>
5259
): Store<S, A, StateExt> & Ext
53-
export default function createStore<S, A extends Action, Ext, StateExt>(
60+
export default function createStore<
61+
S,
62+
A extends Action,
63+
Ext = {},
64+
StateExt = never
65+
>(
5466
reducer: Reducer<S, A>,
5567
preloadedState?: PreloadedState<S> | StoreEnhancer<Ext, StateExt>,
5668
enhancer?: StoreEnhancer<Ext, StateExt>
@@ -110,7 +122,7 @@ export default function createStore<S, A extends Action, Ext, StateExt>(
110122
*
111123
* @returns The current state tree of your application.
112124
*/
113-
function getState(): S & StateExt {
125+
function getState(): ExtendState<S, StateExt> {
114126
if (isDispatching) {
115127
throw new Error(
116128
'You may not call store.getState() while the reducer is executing. ' +
@@ -119,7 +131,7 @@ export default function createStore<S, A extends Action, Ext, StateExt>(
119131
)
120132
}
121133

122-
return currentState as S & StateExt
134+
return currentState as ExtendState<S, StateExt>
123135
}
124136

125137
/**
@@ -291,7 +303,9 @@ export default function createStore<S, A extends Action, Ext, StateExt>(
291303
}
292304

293305
function observeState() {
294-
const observerAsObserver = observer as Observer<S>
306+
const observerAsObserver = observer as Observer<
307+
ExtendState<S, StateExt>
308+
>
295309
if (observerAsObserver.next) {
296310
observerAsObserver.next(getState())
297311
}
@@ -313,11 +327,12 @@ export default function createStore<S, A extends Action, Ext, StateExt>(
313327
// the initial state tree.
314328
dispatch({ type: ActionTypes.INIT } as A)
315329

316-
return ({
330+
const store = ({
317331
dispatch: dispatch as Dispatch<A>,
318332
subscribe,
319333
getState,
320334
replaceReducer,
321335
[$$observable]: observable
322336
} as unknown) as Store<S, A, StateExt> & Ext
337+
return store
323338
}

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ export {
1919
Store,
2020
StoreCreator,
2121
StoreEnhancer,
22-
StoreEnhancerStoreCreator
22+
StoreEnhancerStoreCreator,
23+
ExtendState
2324
} from './types/store'
2425
// reducers
2526
export {

src/types/store.ts

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@ import { Action, AnyAction } from './actions'
22
import { Reducer } from './reducers'
33
import '../utils/symbol-observable'
44

5+
/**
6+
* Extend the state
7+
*
8+
* This is used by store enhancers and store creators to extend state.
9+
* If there is no state extension, it just returns the state, as is, otherwise
10+
* it returns the state joined with its extension.
11+
*
12+
* Reference for future devs:
13+
* https://github.com/microsoft/TypeScript/issues/31751#issuecomment-498526919
14+
*/
15+
export type ExtendState<State, Extension> = [Extension] extends [never]
16+
? State
17+
: State & Extension
18+
519
/**
620
* Internal "virtual" symbol used to make the `CombinedState` type unique.
721
*/
@@ -108,8 +122,13 @@ export type Observer<T> = {
108122
* @template S The type of state held by this store.
109123
* @template A the type of actions which may be dispatched by this store.
110124
* @template StateExt any extension to state from store enhancers
125+
* @template Ext any extensions to the store from store enhancers
111126
*/
112-
export interface Store<S = any, A extends Action = AnyAction, StateExt = {}> {
127+
export interface Store<
128+
S = any,
129+
A extends Action = AnyAction,
130+
StateExt = never
131+
> {
113132
/**
114133
* Dispatches an action. It is the only way to trigger a state change.
115134
*
@@ -143,7 +162,7 @@ export interface Store<S = any, A extends Action = AnyAction, StateExt = {}> {
143162
*
144163
* @returns The current state tree of your application.
145164
*/
146-
getState(): S & StateExt
165+
getState(): ExtendState<S, StateExt>
147166

148167
/**
149168
* Adds a change listener. It will be called any time an action is
@@ -188,7 +207,7 @@ export interface Store<S = any, A extends Action = AnyAction, StateExt = {}> {
188207
* For more information, see the observable proposal:
189208
* https://github.com/tc39/proposal-observable
190209
*/
191-
[Symbol.observable](): Observable<S & StateExt>
210+
[Symbol.observable](): Observable<ExtendState<S, StateExt>>
192211
}
193212

194213
/**
@@ -203,18 +222,14 @@ export interface Store<S = any, A extends Action = AnyAction, StateExt = {}> {
203222
* @template StateExt State extension that is mixed into the state type.
204223
*/
205224
export interface StoreCreator {
206-
<S, A extends Action>(
207-
reducer: Reducer<S, A>,
208-
preloadedState?: PreloadedState<S>
209-
): Store<S, A>
210-
<S, A extends Action, Ext, StateExt>(
225+
<S, A extends Action, Ext = {}, StateExt = never>(
211226
reducer: Reducer<S, A>,
212-
enhancer: StoreEnhancer<Ext, StateExt>
227+
enhancer?: StoreEnhancer<Ext, StateExt>
213228
): Store<S, A, StateExt> & Ext
214-
<S, A extends Action, Ext, StateExt>(
229+
<S, A extends Action, Ext = {}, StateExt = never>(
215230
reducer: Reducer<S, A>,
216-
preloadedState: PreloadedState<S>,
217-
enhancer: StoreEnhancer<Ext, StateExt>
231+
preloadedState?: PreloadedState<S>,
232+
enhancer?: StoreEnhancer<Ext>
218233
): Store<S, A, StateExt> & Ext
219234
}
220235

@@ -239,10 +254,10 @@ export interface StoreCreator {
239254
* @template Ext Store extension that is mixed into the Store type.
240255
* @template StateExt State extension that is mixed into the state type.
241256
*/
242-
export type StoreEnhancer<Ext = {}, StateExt = {}> = (
243-
next: StoreEnhancerStoreCreator
257+
export type StoreEnhancer<Ext = {}, StateExt = never> = (
258+
next: StoreEnhancerStoreCreator<Ext, StateExt>
244259
) => StoreEnhancerStoreCreator<Ext, StateExt>
245-
export type StoreEnhancerStoreCreator<Ext = {}, StateExt = {}> = <
260+
export type StoreEnhancerStoreCreator<Ext = {}, StateExt = never> = <
246261
S = any,
247262
A extends Action = AnyAction
248263
>(

test/typescript/enhancers.ts

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,7 @@ function stateExtension() {
6363
reducer: Reducer<S, A>,
6464
preloadedState?: any
6565
) => {
66-
const wrapReducer = (
67-
reducer: Reducer<S, A>
68-
): Reducer<S & ExtraState, A> => (state, action) => {
66+
const wrappedReducer: Reducer<S & ExtraState, A> = (state, action) => {
6967
const newState = reducer(state, action)
7068
return {
7169
...newState,
@@ -78,13 +76,7 @@ function stateExtension() {
7876
extraField: 'extra'
7977
}
8078
: undefined
81-
const store = createStore(wrapReducer(reducer), wrappedPreloadedState)
82-
return {
83-
...store,
84-
replaceReducer(nextReducer: Reducer<S, A>) {
85-
store.replaceReducer(wrapReducer(nextReducer))
86-
}
87-
}
79+
return createStore(wrappedReducer, wrappedPreloadedState)
8880
}
8981

9082
const store = createStore(reducer, enhancer)
@@ -103,10 +95,8 @@ function extraMethods() {
10395
...args
10496
) => {
10597
const store = createStore(...args)
106-
return {
107-
...store,
108-
method: () => 'foo'
109-
}
98+
store.method = () => 'foo'
99+
return store
110100
}
111101

112102
const store = createStore(reducer, enhancer)
@@ -145,10 +135,7 @@ function replaceReducerExtender() {
145135
extraField: 'extra'
146136
}
147137
: undefined
148-
return {
149-
...createStore(wrappedReducer, wrappedPreloadedState),
150-
method: () => 'foo'
151-
}
138+
return createStore(wrappedReducer, wrappedPreloadedState)
152139
}
153140

154141
const store = createStore(reducer, enhancer)

test/typescript/store.ts

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import {
55
Action,
66
StoreEnhancer,
77
Unsubscribe,
8-
Observer
8+
Observer,
9+
ExtendState
910
} from '../..'
1011
import 'symbol-observable'
1112

@@ -17,6 +18,41 @@ type State = {
1718
}
1819
}
1920

21+
/* extended state */
22+
const noExtend: ExtendState<State, never> = {
23+
a: 'a',
24+
b: {
25+
c: 'c',
26+
d: 'd'
27+
}
28+
}
29+
// typings:expect-error
30+
const noExtendError: ExtendState<State, never> = {
31+
a: 'a',
32+
b: {
33+
c: 'c',
34+
d: 'd'
35+
},
36+
e: 'oops'
37+
}
38+
39+
const yesExtend: ExtendState<State, { yes: 'we can' }> = {
40+
a: 'a',
41+
b: {
42+
c: 'c',
43+
d: 'd'
44+
},
45+
yes: 'we can'
46+
}
47+
// typings:expect-error
48+
const yesExtendError: ExtendState<State, { yes: 'we can' }> = {
49+
a: 'a',
50+
b: {
51+
c: 'c',
52+
d: 'd'
53+
}
54+
}
55+
2056
interface DerivedAction extends Action {
2157
type: 'a'
2258
b: 'b'
@@ -84,9 +120,9 @@ const storeWithActionReducerAndBadPreloadedState = createStore(
84120

85121
const enhancer: StoreEnhancer = next => next
86122

87-
const storeWithSpecificEnhancer = createStore(reducer, enhancer)
123+
const storeWithSpecificEnhancer: Store<State> = createStore(reducer, enhancer)
88124

89-
const storeWithPreloadedStateAndEnhancer = createStore(
125+
const storeWithPreloadedStateAndEnhancer: Store<State> = createStore(
90126
reducer,
91127
{
92128
a: 'a',

0 commit comments

Comments
 (0)