Skip to content

Instantly share code, notes, and snippets.

@typoerr
Last active July 22, 2017 13:44
Show Gist options
  • Select an option

  • Save typoerr/423348d4ee7a2b3e9c410964524a9258 to your computer and use it in GitHub Desktop.

Select an option

Save typoerr/423348d4ee7a2b3e9c410964524a9258 to your computer and use it in GitHub Desktop.
redux-utils
import { MiddlewareAPI } from 'redux';
export type EnhancedStore<T, A> = T & {
dispatch: <K extends keyof A>(type: K, payload: A[K]) => {
type: K, payload: A[K]
}
};
export default function makeTypedDispatch<T extends MiddlewareAPI<any>, A>(store: T): EnhancedStore<T, A> {
const origin = store.dispatch;
return Object.assign({}, store, { dispatch });
function dispatch<K extends keyof A>(type: K, payload: A[K]) {
const action = (typeof type === 'string') ? { type, payload } : type;
return origin(action);
}
}
import enhance from './make-typed-dispatch';
import { createStore } from 'redux';
interface S {
count: number;
}
interface A {
increment: number;
decrement: number;
}
const reducer = (s: S = { count: 0 }, action: any) => {
switch (action.type) {
case 'increment':
return { ...s, count: s.count + action.payload };
case 'decrement':
return { ...s, count: s.count - action.payload };
default:
return s;
}
};
describe('make-typed-dispatch', () => {
test('from key value', (end) => {
expect.assertions(1);
const store = createStore<S>(reducer);
const enhanced = enhance<typeof store, A>(store);
store.subscribe(() => {
expect(store.getState()).toEqual({ count: 1 });
end();
});
enhanced.dispatch('increment', 1);
});
test('from action object', (end) => {
expect.assertions(1);
const store = createStore<S>(reducer);
const enhanced = enhance<typeof store, A>(store);
store.subscribe(() => {
expect(store.getState()).toEqual({ count: 1 });
end();
});
enhanced.dispatch({ type: 'increment', payload: 1 });
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment