Skip to content

Instantly share code, notes, and snippets.

@fasetto
Last active April 26, 2018 11:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fasetto/dc1a4be1d3384dcb45c17322c27e634e to your computer and use it in GitHub Desktop.
Save fasetto/dc1a4be1d3384dcb45c17322c27e634e to your computer and use it in GitHub Desktop.
TypeScript FSA Sample
import { Action, ActionWithPayload } from './types';
export function createAction<T extends string>(type: T): Action<T>;
export function createAction<T extends string, P>(type: T, payload: P): ActionWithPayload<T, P>;
export function createAction<T extends string, P>(type: T, payload?: P) {
return payload === undefined ? { type } : { type, payload };
}
import { ActionsUnion } from './types';
import { createAction } from './action-helpers';
export enum ActionTypes {
SET_AGE = '[core] set age',
SET_NAME = '[core] set name',
RELOAD_URL = '[core] reload page'
}
export const Actions = {
setAge: (age: number) => createAction(ActionTypes.SET_AGE, age),
setName: (name: string) => createAction(ActionTypes.SET_NAME, name),
reloadUrl: () => createAction(ActionTypes.RELOAD_URL)
};
export type Actions = ActionsUnion<typeof Actions>;
import { Actions, ActionTypes } from './actions';
export interface State {
user: { age: number, name: string } | {};
reloadPage: boolean;
}
export const initialState: State = {
user: {},
reloadPage: false
};
export const reducer = (state = initialState, action: Actions): State => {
switch (action.type) {
case ActionTypes.SET_AGE: {
const { payload: newAge } = action;
const newUser = { ...state.user, age: newAge };
const newState = { ...state, user: newUser };
return newState;
}
case ActionTypes.SET_NAME: {
const { payload: newName } = action;
const newUser = { ...state.user, name: newName };
const newState = { ...state, user: newUser };
return newState;
}
case ActionTypes.RELOAD_URL: {
return {
...state,
reloadPage: true
};
}
default:
return state;
}
};
import { createStore, combineReducers, Reducer } from 'redux';
import * as fromRoot from '../containers/App/reducer';
// const composeEnhancers = (
// process.env.NODE_ENV === 'development' &&
// (window as any).__REDUX_DEVTOOLS_EXTENSION__ &&
// (window as any).__REDUX_DEVTOOLS_EXTENSION__()
// ) || compose;
// const enhancer = composeEnhancers(); /* Middlewares etc. */
// [P]roperty in keyof [S]tate
type ReducersMapObject<S> = { [P in keyof S]: Reducer<S[P]> };
export interface State {
root: fromRoot.State;
}
const reducers: ReducersMapObject<State> = {
root: fromRoot.reducer
};
const initialState = {} as State;
export default createStore(combineReducers(reducers), initialState);
export interface Action<T extends string> {
type: T;
}
export interface ActionWithPayload<T extends string, P> extends Action<T> {
payload: P;
}
type FunctionType = (...args: any[]) => any;
type ActionCreatorsMapObject = { [actionCreator: string]: FunctionType };
export type ActionsUnion<A extends ActionCreatorsMapObject> = ReturnType<A[keyof A]>;
export type ActionsOfType<ActionUnion, ActionType extends string> = ActionUnion extends Action<
ActionType
>
? ActionUnion
: never;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment