Skip to content

Instantly share code, notes, and snippets.

@icorbrey
Last active March 4, 2020 15:51
Show Gist options
  • Save icorbrey/53e94031d443f93bd0289b11bfb268cb to your computer and use it in GitHub Desktop.
Save icorbrey/53e94031d443f93bd0289b11bfb268cb to your computer and use it in GitHub Desktop.
Typechecked Redux middleware generator
import { AnyAction, Dispatch, Middleware, MiddlewareAPI } from 'redux'
/**
* Function to convert into middleware.
*
* @template S The state type to provide to the function.
* @template A The action type to provide to the function.
*
* @param store Redux store object of type <S>.
* @param next The next dispatch object.
* @param action Redux action object of type <A>.
*/
export type MiddlewareFunction<S, A> = (
store: MiddlewareAPI<Dispatch<AnyAction>, S>,
next: Dispatch<AnyAction>,
action: A
) => any
/**
* Map of middleware functions to property names.
*
* @template K Union type containing the names of all middleware functions in
* the object.
* @template S The state type to provide to functions.
* @template A The action type to provide to functions.
*/
export type MiddlewareFunctionCollection<K extends string, S, A> = {
[key in K]: MiddlewareFunction<S, A>
}
/**
* Map of middlewares to property names.
*
* @template K Union type containing the names of all middlewares in the object.
* @template S The state type to provide to middlewares.
*/
export type MiddlewareCollection<K extends string, S> = {
[key in K]: Middleware<{}, S>
}
/**
* Maps middleware functions from the given middleware function collection to a
* middleware collection. Middleware functions should be fully typechecked if
* the proper types are given to the function.
*
* @template K Union type containing the names of all middlewares.
* @template S The state type to provide to middlewares.
* @template A The action type to provide to middlewares.
*
* @param middleware An object with middlewares as its children. It must contain
* all of the values in the union type K as its properties.
*
* @returns An object with each middleware function mapped to its proper
* middleware. Returned object should be fully typechecked for export.
*/
export default <K extends string, S, A extends AnyAction>(middleware: MiddlewareFunctionCollection<K, S, A>): MiddlewareCollection<K, S> =>
{
const results: MiddlewareCollection<K, S> = {} as any
(Object.keys(middleware) as K[])
.forEach(name => results[name] =
store => next => action =>
middleware[name](store, next, action))
return results
}
export type MiddlewareNames =
	'duplicateMiddleware',
	'loggingMiddleware'

export default createMiddleware<MiddlewareNames, StateType, ActionTypes>({
	
	duplicateMiddleware: (state, next, action) =>
	{
		// Do middleware things...
		
		return next(action)
	},
																		 
	loggingMiddleware: (state, next, action) =>
	{
		// Do middleware things...
		
		return next(action)
	}
})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment