There are only two hard things in Computer Science: cache invalidation and naming things. -- PHil Karlton
Why give names to actions when your action and reducer can discriminate an action based on type (e.g., MyJobActionType) ?
export const enum MyJobActionType { MY_JOB = 'MY_JOB', MY_JOB_UI = 'MY_JOB_UI', MY_JOB_DATA_FETCHING = 'MY_JOB_DATA_FETCHING', MY_JOB_DATA_FETCHED = 'MY_JOB_DATA_FETCHED', } export type MyJobAction = IMyJobAction | IMyJobUIAction | IMyJobDataFetchingAction | IMyJobDataFetchedAction; interface IMyJobAction extends Action { type: MyJobActionType.MY_JOB; payload?: { jobId: 'new' | number; }; } interface IMyJobUIAction extends Action { type: MyJobActionType.MY_JOB_UI; ui: React.ComponentClass; } interface IMyJobDataFetchingAction extends Action { type: MyJobActionType.MY_JOB_DATA_FETCHING; } interface IMyJobDataFetchedAction extends Action { type: MyJobActionType.MY_JOB_DATA_FETCHED; data: IPagedDto<IPagedMyJobPostDto>; }
Reducer:
export const myJobViewModelReducer = produce(( draft: IMyJobViewModel = { view : null, model: { gridData: no.data } }, action: MyJobAction ) =>
Action:
async function loadUI(dispatch: Dispatch<MyJobAction>) { const component = (await import(/* webpackChunkName: 'myJob' */ './')).default; const uiAction: MyJobAction = { type: MyJobActionType.MY_JOB_UI, ui : component }; await dispatch(uiAction); }
So don't name things then:
export type MyJobAction = { type: MyJobActionType.MY_JOB; payload?: { jobId: 'new' | number; }; } | { type: MyJobActionType.MY_JOB_UI; ui: React.ComponentClass; } | { type: MyJobActionType.MY_JOB_DATA_FETCHING; } | { type: MyJobActionType.MY_JOB_DATA_FETCHED; data: IPagedDto<IPagedMyJobPostDto>; } ;
Are you worried someone might use the wrong payload (e.g., payload, ui, data) when dispatching an action? Don't worry, TypeScript is a smart language.

And just like that, TypeScript can infer that only the ui property is if a good discriminator is used, e.g., type: MyJobActionType.MY_JOB_UI



Finally, correct the properties of the object structure that matches type: MyJobActionType.MY_JOB_UI

Less interfaces, less names need to come up with.