Skip to content

Commit

Permalink
Improve typings for Middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
David Hahn committed Jul 26, 2017
1 parent 64fee67 commit d59de69
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 7 deletions.
8 changes: 6 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,11 @@ export interface MiddlewareAPI<S> {
* logging actions, performing side effects like routing, or turning an
* asynchronous API call into a series of synchronous actions.
*/
export interface Middleware {
export interface Middleware<S> {
(api: MiddlewareAPI<S>): (next: Dispatch<S>) => Dispatch<S>;
}

export interface GenericMiddleware {
<S>(api: MiddlewareAPI<S>): (next: Dispatch<S>) => Dispatch<S>;
}

Expand All @@ -299,7 +303,7 @@ export interface Middleware {
* @param middlewares The middleware chain to be applied.
* @returns A store enhancer applying the middleware.
*/
export function applyMiddleware(...middlewares: Middleware[]): GenericStoreEnhancer;
export function applyMiddleware(...middlewares: GenericMiddleware[]): GenericStoreEnhancer;


/* action creators */
Expand Down
34 changes: 29 additions & 5 deletions test/typescript/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
Middleware, MiddlewareAPI,
Middleware, GenericMiddleware, MiddlewareAPI,
applyMiddleware, createStore, Dispatch, Reducer, Action
} from "../../index";

Expand All @@ -11,7 +11,15 @@ declare module "../../index" {

type Thunk<S, O> = (dispatch: Dispatch<S>, getState: () => S) => O;

const thunkMiddleware: Middleware =
const thunkSpecificMiddleware: Middleware<State> =
({dispatch, getState}: MiddlewareAPI<State>) =>
(next: Dispatch<State>) =>
<A extends Action, B>(action: A | Thunk<State, B>): B|Action =>
typeof action === 'function' ?
(<Thunk<State, B>>action)(dispatch, getState) :
next(<A>action)

const thunkGenericMiddleware: GenericMiddleware =
<S>({dispatch, getState}: MiddlewareAPI<S>) =>
(next: Dispatch<S>) =>
<A extends Action, B>(action: A | Thunk<S, B>): B|Action =>
Expand All @@ -20,7 +28,23 @@ const thunkMiddleware: Middleware =
next(<A>action)


const loggerMiddleware: Middleware =
const loggerSpecificMiddleware: Middleware<State> =
({getState}: MiddlewareAPI<State>) =>
(next: Dispatch<State>) =>
(action: any): any => {
console.log('will dispatch', action)

// Call the next dispatch method in the middleware chain.
const returnValue = next(action)

console.log('state after dispatch', getState())

// This will likely be the action itself, unless
// a middleware further in chain changed it.
return returnValue
}

const loggerGenericMiddleware: GenericMiddleware =
<S>({getState}: MiddlewareAPI<S>) =>
(next: Dispatch<S>) =>
(action: any): any => {
Expand All @@ -47,7 +71,7 @@ const reducer: Reducer<State> = (state: State, action: Action): State => {

const storeWithThunkMiddleware = createStore(
reducer,
applyMiddleware(thunkMiddleware)
applyMiddleware(thunkGenericMiddleware)
);

storeWithThunkMiddleware.dispatch(
Expand All @@ -60,5 +84,5 @@ storeWithThunkMiddleware.dispatch(

const storeWithMultipleMiddleware = createStore(
reducer,
applyMiddleware(loggerMiddleware, thunkMiddleware)
applyMiddleware(loggerGenericMiddleware, thunkGenericMiddleware)
)

0 comments on commit d59de69

Please sign in to comment.