Skip to content

Instantly share code, notes, and snippets.

@quicksnap
Created January 15, 2018 23:28
Show Gist options
  • Save quicksnap/6dd75c763da669d1b833a58fd36fd196 to your computer and use it in GitHub Desktop.
Save quicksnap/6dd75c763da669d1b833a58fd36fd196 to your computer and use it in GitHub Desktop.
type IActionType<X> = X & { __actionType: string; };
const _devSet: { [key: string]: any } = {};
// __actionType is used as the sentinal value in the `isAction` type guard
// functions. We need this so we can simply use the action creator
// function as the action type itself.
// typePrefix allows different types of actions (middleware) to avoid any collisions
function makeAction<Z extends {}>(type: string, typePrefix = '') {
// Helpful check against copy-pasting duplicate type keys when creating
// new actions.
if (__DEV__) {
if (_devSet[type]) {
throw new Error(
'Attempted creating an action with an existing type key. ' +
'This is almost cetainly an error.',
);
}
_devSet[type] = type;
}
return <X extends (...args: any[]) => Z>(fn: X) => {
const returnFn: IActionType<X> = (
(...args: any[]) => ({ ...(fn as any)(...args), type })
) as any;
returnFn.__actionType = typePrefix + type;
return returnFn;
};
}
// This version forces action to have a `payload` key. You may need to
// adjust it to your needs, or remove the `extends` suffix entirely.
export function isAction<T extends { payload: any }>(
action: Action,
actionCreator: IActionType<(...args: any[]) => T>,
): action is T & Action {
return action.type === actionCreator.__actionType;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment