import Images from "~/state/images/actions"; import Users from "~/state/users/actions"; import Galleries from "~/state/galleries/actions"; import { Dispatch } from "redux"; interface BaseActions { images: Images; users: Users; galleries: Galleries; } /** * Narrows to { images: ImagesActions, users: never, etc } */ type FilteredActions = { [Key in keyof B]: A extends B[Key] ? B[Key] : never }; const incomingAction = Images.fetchImages("wheredidthesodago"); type IncomingFiltered = FilteredActions; /** * Narrows to ResourceActions */ type ActionType = FilteredActions[keyof BaseActions]; type IncomingType = ActionType; type AllActions = ActionType; const logEvent = (resource: string, action: A) => { console.log( `#### fired ${resource} - Action ${action.type}`, action.payload || "" ); }; type LogFunction = (action: ActionType) => void; const logFunctions = { images: logEvent.bind(this, "IMAGES"), users: logEvent.bind(this, "USERS"), galleries: logEvent.bind(this, "GALLERIES") }; const trackEvent = (action: ActionType) => { const { type } = action; const resource = type.split(".")[0] as keyof typeof logFunctions; const logFn: LogFunction = logFunctions[resource]; logFn(action); }; const analyticsMiddleware = ({ dispatch, getState }: { dispatch: Dispatch; getState(): RootState; }) => { return (next: any) => (action: ActionType) => { trackEvent(action); return next(action); }; }; export default analyticsMiddleware;