Skip to content

Instantly share code, notes, and snippets.

@evaldosantos
Created October 8, 2018 21:36
Show Gist options
  • Save evaldosantos/7f604d1e6de46b62bf8bb669f137089a to your computer and use it in GitHub Desktop.
Save evaldosantos/7f604d1e6de46b62bf8bb669f137089a to your computer and use it in GitHub Desktop.
interface Action {
type: string;
payload?: any;
}
interface Reducer<T> {
(state: T, action: Action): T
}
interface ListenerCallback {
(): void;
}
interface UnsubscribeCallback {
(): void;
}
class Store<T> {
private _state: T;
private _listeners: ListenerCallback[] = [];
constructor( private reducer: Reducer<T>, initialState: T ) {
this._state = initialState;
}
getState(): T {
return this._state;
}
dispatch(action: Action): void {
this._state = this.reducer(this._state, action);
this._listeners.forEach((listener: ListenerCallback) => listener());
}
subscribe(listener: ListenerCallback): UnsubscribeCallback {
this._listeners.push(listener);
return () => { // returns an "unsubscribe" function
this._listeners = this._listeners.filter(l => l !== listener);
};
}
}
let reducer: Reducer<number> = (state: number, action: Action) => {
switch( action.type ) {
case 'INCREMENT':
return state + 1;
case 'DECREMENT':
return state - 1;
case 'PLUS':
return state + action.payload;
default:
return state;
}
}
let incrementAction: Action = { type: 'INCREMENT' };
let decrementAction: Action = { type: 'DECREMENT' };
// By default, reducers return the original state.
// console.log(reducer(0, null));
console.log(reducer(0, incrementAction));
console.log(reducer(1, incrementAction));
console.log(reducer(2, decrementAction));
let unknownAction: Action = { type: 'UNKNOWN' };
console.log(reducer(100, unknownAction)); // -> 100
console.log( reducer(3, { type: 'PLUS', payload: 7 }) );
console.log( reducer(3, { type: 'PLUS', payload: 9000 }) );
console.log( reducer(3, { type: 'PLUS', payload: -2 }) );
// create a new store
let store = new Store<number>(reducer, 0);
// console.log(store.getState()); // -> 0
// subscribe
let unsubscribe = store.subscribe(() => {
console.log('subscribed: ', store.getState());
});
store.dispatch(incrementAction);
console.log(store.getState()); // -> 1
store.dispatch(incrementAction);
console.log(store.getState()); // -> 2
unsubscribe();
store.dispatch(decrementAction);
console.log(store.getState()); // -> 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment