Skip to content

Commit 3388903

Browse files
committed
Merge pull request #1537 from Igorbek/ts-def-improv
Add state type to dispatch interface
2 parents e6d1780 + 658fa6f commit 3388903

File tree

4 files changed

+32
-21
lines changed

4 files changed

+32
-21
lines changed

index.d.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,9 @@ export function combineReducers<S>(reducers: ReducersMapObject): Reducer<S>;
9393
* transform, delay, ignore, or otherwise interpret actions or async actions
9494
* before passing them to the next middleware.
9595
*/
96-
export type Dispatch = (action: any) => any;
96+
export interface Dispatch<S> {
97+
<A extends Action>(action: A): A;
98+
}
9799

98100
/**
99101
* Function to remove listener added by `Store.subscribe()`.
@@ -136,7 +138,7 @@ export interface Store<S> {
136138
* Note that, if you use a custom middleware, it may wrap `dispatch()` to
137139
* return something else (for example, a Promise you can await).
138140
*/
139-
dispatch: Dispatch;
141+
dispatch: Dispatch<S>;
140142

141143
/**
142144
* Reads the state tree managed by the store.
@@ -251,7 +253,7 @@ export const createStore: StoreCreator;
251253
/* middleware */
252254

253255
export interface MiddlewareAPI<S> {
254-
dispatch: Dispatch;
256+
dispatch: Dispatch<S>;
255257
getState(): S;
256258
}
257259

@@ -265,7 +267,7 @@ export interface MiddlewareAPI<S> {
265267
* asynchronous API call into a series of synchronous actions.
266268
*/
267269
export interface Middleware {
268-
<S>(api: MiddlewareAPI<S>): (next: Dispatch) => (action: any) => any;
270+
<S>(api: MiddlewareAPI<S>): (next: Dispatch<S>) => Dispatch<S>;
269271
}
270272

271273
/**
@@ -337,19 +339,19 @@ export interface ActionCreatorsMapObject {
337339
* creator wrapped into the `dispatch` call. If you passed a function as
338340
* `actionCreator`, the return value will also be a single function.
339341
*/
340-
export function bindActionCreators<A extends ActionCreator<any>>(actionCreator: A, dispatch: Dispatch): A;
342+
export function bindActionCreators<A extends ActionCreator<any>>(actionCreator: A, dispatch: Dispatch<any>): A;
341343

342344
export function bindActionCreators<
343345
A extends ActionCreator<any>,
344346
B extends ActionCreator<any>
345-
>(actionCreator: A, dispatch: Dispatch): B;
347+
>(actionCreator: A, dispatch: Dispatch<any>): B;
346348

347-
export function bindActionCreators<M extends ActionCreatorsMapObject>(actionCreators: M, dispatch: Dispatch): M;
349+
export function bindActionCreators<M extends ActionCreatorsMapObject>(actionCreators: M, dispatch: Dispatch<any>): M;
348350

349351
export function bindActionCreators<
350352
M extends ActionCreatorsMapObject,
351353
N extends ActionCreatorsMapObject
352-
>(actionCreators: M, dispatch: Dispatch): N;
354+
>(actionCreators: M, dispatch: Dispatch<any>): N;
353355

354356

355357
/* compose */

test/typescript/actionCreators.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ const addTodo: ActionCreator<AddTodoAction> = (text: string) => ({
1515

1616
const addTodoAction: AddTodoAction = addTodo('test');
1717

18-
type AddTodoThunk = (dispatch: Dispatch) => AddTodoAction;
18+
type AddTodoThunk = (dispatch: Dispatch<any>) => AddTodoAction;
1919

2020
const addTodoViaThunk: ActionCreator<AddTodoThunk> = (text: string) =>
21-
(dispatch: Dispatch) => ({
21+
(dispatch: Dispatch<any>) => ({
2222
type: 'ADD_TODO',
2323
text
2424
})
2525

26-
declare const dispatch: Dispatch;
26+
declare const dispatch: Dispatch<any>;
2727

2828
const boundAddTodo = bindActionCreators(addTodo, dispatch);
2929

test/typescript/dispatch.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import {Dispatch, Action} from "../../index.d.ts";
22

33

4-
declare const dispatch: Dispatch;
5-
4+
declare const dispatch: Dispatch<any>;
65

76
const dispatchResult: Action = dispatch({type: 'TYPE'});
87

9-
10-
type Thunk<O> = () => O;
8+
// thunk
9+
declare module "../../index.d.ts" {
10+
export interface Dispatch<S> {
11+
<R>(asyncAction: (dispatch: Dispatch<S>, getState: () => S) => R): R;
12+
}
13+
}
1114

1215
const dispatchThunkResult: number = dispatch(() => 42);
16+
const dispatchedTimerId: number = dispatch(d => setTimeout(() => d({type: 'TYPE'}), 1000));

test/typescript/middleware.ts

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,26 @@ import {
33
applyMiddleware, createStore, Dispatch, Reducer, Action
44
} from "../../index.d.ts";
55

6+
declare module "../../index.d.ts" {
7+
export interface Dispatch<S> {
8+
<R>(asyncAction: (dispatch: Dispatch<S>, getState: () => S) => R): R;
9+
}
10+
}
611

7-
type Thunk<S, O> = (dispatch: Dispatch, getState?: () => S) => O;
12+
type Thunk<S, O> = (dispatch: Dispatch<S>, getState: () => S) => O;
813

914
const thunkMiddleware: Middleware =
1015
<S>({dispatch, getState}: MiddlewareAPI<S>) =>
11-
(next: Dispatch) =>
12-
<A, B>(action: A | Thunk<S, B>): B =>
16+
(next: Dispatch<S>) =>
17+
<A extends Action, B>(action: A | Thunk<S, B>): B|Action =>
1318
typeof action === 'function' ?
1419
(<Thunk<S, B>>action)(dispatch, getState) :
15-
<B>next(<A>action)
20+
next(<A>action)
1621

1722

1823
const loggerMiddleware: Middleware =
1924
<S>({getState}: MiddlewareAPI<S>) =>
20-
(next: Dispatch) =>
25+
(next: Dispatch<S>) =>
2126
(action: any): any => {
2227
console.log('will dispatch', action)
2328

@@ -47,7 +52,7 @@ const storeWithThunkMiddleware = createStore(
4752
);
4853

4954
storeWithThunkMiddleware.dispatch(
50-
(dispatch: Dispatch, getState: () => State) => {
55+
(dispatch, getState) => {
5156
const todos: string[] = getState().todos;
5257
dispatch({type: 'ADD_TODO'})
5358
}

0 commit comments

Comments
 (0)