Skip to content

Commit 956b0e9

Browse files
cellogtimdorr
authored andcommitted
extract middleware types from index.d.ts (reduxjs#3543)
* extract middleware types from index.d.ts * move PreloadedState/CombinedState into types/store.ts
1 parent 0c70abc commit 956b0e9

File tree

3 files changed

+96
-40
lines changed

3 files changed

+96
-40
lines changed

src/types/middleware.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { Dispatch } from './store'
2+
import { AnyAction } from './actions'
3+
4+
export interface MiddlewareAPI<D extends Dispatch = Dispatch, S = any> {
5+
dispatch: D
6+
getState(): S
7+
}
8+
9+
/**
10+
* A middleware is a higher-order function that composes a dispatch function
11+
* to return a new dispatch function. It often turns async actions into
12+
* actions.
13+
*
14+
* Middleware is composable using function composition. It is useful for
15+
* logging actions, performing side effects like routing, or turning an
16+
* asynchronous API call into a series of synchronous actions.
17+
*
18+
* @template DispatchExt Extra Dispatch signature added by this middleware.
19+
* @template S The type of the state supported by this middleware.
20+
* @template D The type of Dispatch of the store where this middleware is
21+
* installed.
22+
*/
23+
export interface Middleware<
24+
_DispatchExt = {}, // TODO: remove unused component
25+
S = any,
26+
D extends Dispatch = Dispatch
27+
> {
28+
(api: MiddlewareAPI<D, S>): (
29+
next: Dispatch<AnyAction>
30+
) => (action: any) => any
31+
}

src/types/reducers.ts

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,4 @@
11
import { Action, AnyAction } from './actions'
2-
/**
3-
* Internal "virtual" symbol used to make the `CombinedState` type unique.
4-
*/
5-
declare const $CombinedState: unique symbol
6-
7-
/**
8-
* State base type for reducers created with `combineReducers()`.
9-
*
10-
* This type allows the `createStore()` method to infer which levels of the
11-
* preloaded state can be partial.
12-
*
13-
* Because Typescript is really duck-typed, a type needs to have some
14-
* identifying property to differentiate it from other types with matching
15-
* prototypes for type checking purposes. That's why this type has the
16-
* `$CombinedState` symbol property. Without the property, this type would
17-
* match any object. The symbol doesn't really exist because it's an internal
18-
* (i.e. not exported), and internally we never check its value. Since it's a
19-
* symbol property, it's not expected to be unumerable, and the value is
20-
* typed as always undefined, so its never expected to have a meaningful
21-
* value anyway. It just makes this type distinquishable from plain `{}`.
22-
*/
23-
export type CombinedState<S> = { readonly [$CombinedState]?: undefined } & S
24-
25-
/**
26-
* Recursively makes combined state objects partial. Only combined state _root
27-
* objects_ (i.e. the generated higher level object with keys mapping to
28-
* individual reducers) are partial.
29-
*/
30-
export type PreloadedState<S> = Required<S> extends {
31-
[$CombinedState]: undefined
32-
}
33-
? S extends CombinedState<infer S1>
34-
? {
35-
[K in keyof S1]?: S1[K] extends object ? PreloadedState<S1[K]> : S1[K]
36-
}
37-
: never
38-
: {
39-
[K in keyof S]: S[K] extends object ? PreloadedState<S[K]> : S[K]
40-
}
412

423
/* reducers */
434

src/types/store.ts

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,72 @@
11
/// <reference types="symbol-observable" />
2-
import { Dispatch, PreloadedState } from '../..'
32
import { Action, AnyAction } from './actions'
43
import { Reducer } from './reducers'
54

5+
/**
6+
* Internal "virtual" symbol used to make the `CombinedState` type unique.
7+
*/
8+
declare const $CombinedState: unique symbol
9+
10+
/**
11+
* State base type for reducers created with `combineReducers()`.
12+
*
13+
* This type allows the `createStore()` method to infer which levels of the
14+
* preloaded state can be partial.
15+
*
16+
* Because Typescript is really duck-typed, a type needs to have some
17+
* identifying property to differentiate it from other types with matching
18+
* prototypes for type checking purposes. That's why this type has the
19+
* `$CombinedState` symbol property. Without the property, this type would
20+
* match any object. The symbol doesn't really exist because it's an internal
21+
* (i.e. not exported), and internally we never check its value. Since it's a
22+
* symbol property, it's not expected to be unumerable, and the value is
23+
* typed as always undefined, so its never expected to have a meaningful
24+
* value anyway. It just makes this type distinquishable from plain `{}`.
25+
*/
26+
export type CombinedState<S> = { readonly [$CombinedState]?: undefined } & S
27+
28+
/**
29+
* Recursively makes combined state objects partial. Only combined state _root
30+
* objects_ (i.e. the generated higher level object with keys mapping to
31+
* individual reducers) are partial.
32+
*/
33+
export type PreloadedState<S> = Required<S> extends {
34+
[$CombinedState]: undefined
35+
}
36+
? S extends CombinedState<infer S1>
37+
? {
38+
[K in keyof S1]?: S1[K] extends object ? PreloadedState<S1[K]> : S1[K]
39+
}
40+
: never
41+
: {
42+
[K in keyof S]: S[K] extends object ? PreloadedState<S[K]> : S[K]
43+
}
44+
45+
/**
46+
* A *dispatching function* (or simply *dispatch function*) is a function that
47+
* accepts an action or an async action; it then may or may not dispatch one
48+
* or more actions to the store.
49+
*
50+
* We must distinguish between dispatching functions in general and the base
51+
* `dispatch` function provided by the store instance without any middleware.
52+
*
53+
* The base dispatch function *always* synchronously sends an action to the
54+
* store's reducer, along with the previous state returned by the store, to
55+
* calculate a new state. It expects actions to be plain objects ready to be
56+
* consumed by the reducer.
57+
*
58+
* Middleware wraps the base dispatch function. It allows the dispatch
59+
* function to handle async actions in addition to actions. Middleware may
60+
* transform, delay, ignore, or otherwise interpret actions or async actions
61+
* before passing them to the next middleware.
62+
*
63+
* @template A The type of things (actions or otherwise) which may be
64+
* dispatched.
65+
*/
66+
export interface Dispatch<A extends Action = AnyAction> {
67+
<T extends A>(action: T, ...extraArgs: any[]): T
68+
}
69+
670
/**
771
* Function to remove listener added by `Store.subscribe()`.
872
*/

0 commit comments

Comments
 (0)