Skip to content

Instantly share code, notes, and snippets.

@typoerr
Created January 26, 2018 00:00
Show Gist options
  • Save typoerr/86abd798994c4800874a49117988f617 to your computer and use it in GitHub Desktop.
Save typoerr/86abd798994c4800874a49117988f617 to your computer and use it in GitHub Desktop.
typescript-fsa + payload mapper
export interface AnyAction {
type: any
}
export interface Action<P = any> extends AnyAction {
type: string
payload: P
[key: string]: any
}
export interface ActionCreator<P = any, I = P> {
(input: I, extra?: object): Action<P>
type: string
match: (action: any) => action is Action<P>
withMapper: <R>(mapper: (input: P) => R) => ActionCreator<R, P>
}
export function createActionFactory(prefix = '') {
return function actionFactory<P>(type: string) {
type = prefix + type
const createAction: any = (input: P, extra?: any): Action => {
return { type, payload: input, ...extra }
}
createAction.type = type
createAction.match = (action: any) => action != null && action.type === type
createAction.withMapper = withMapper.bind(null, createAction)
return createAction as ActionCreator<P>
}
}
export function withMapper<T, R>(creator: ActionCreator<T>, fn: (input: T) => R) {
const createAction = (input: T, extra?: any) => {
const action = creator(input, extra)
return { ...action, payload: fn(action.payload) }
}
return Object.assign(createAction, creator)
}
const createAction = createActionFactory('foo/')
const addTodo = createAction<string>('ADD_TODO')
.withMapper(content => ({ id: Date.now(), content }))
console.log(addTodo('hello'))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment