Skip to content

Instantly share code, notes, and snippets.

@typoerr
Last active March 11, 2017 05:47
Show Gist options
  • Save typoerr/cf7eac32a80b85aa0d44d8815076253f to your computer and use it in GitHub Desktop.
Save typoerr/cf7eac32a80b85aa0d44d8815076253f to your computer and use it in GitHub Desktop.
Minimal TypeSafe Flux
type ReduceMap<S, T> = {
[P in keyof T]: (state: S, payload: T[P]) => S
};
const createStore = <S, T>(initState: S, reduceMap: ReduceMap<S, T>) => {
let $state = initState;
const $listeners: Function[] = [];
return {
get listenerCount() {
return $listeners.length;
},
getState,
subscribe,
dispatch
};
function getState() {
return $state;
}
function subscribe(listener: Function) {
$listeners.push(listener);
return function unsubscribe() {
const idx = $listeners.findIndex(f => f === listener);
$listeners.splice(idx, 1);
};
}
function dispatch<K extends keyof T>(type: K, payload: T[K]) {
const reducer = reduceMap[type];
if (reducer) {
$state = reducer($state, payload);
$listeners.forEach(f => f());
}
}
};
interface State {
count: number;
}
interface Types {
INCREMENT: number;
DECREMENT: number;
'CONTEXT:FOO': number;
}
const store = createStore<State, Types>({ count: 0 }, {
INCREMENT: (s, p) => ({ count: s.count + p }),
DECREMENT: (s, p) => ({ count: s.count + p }),
'CONTEXT:FOO': (s, p) => ({ count: s.count + p })
});
store.dispatch('INCREMENT', 1);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment