You want the actions to be typed. You should use interface or class.
Class is better than interface because in interfaces you cannot define the action "type" as a constant, but in classes you can:
class LoadingStartedAction implements Action{
readonly type = LOADING_STARTED
}
However a class instance is not a plain object, but Redux requires plain objects to be dispatched.
This can be handled by a middleware which converts the class instances to plain objects
// See https://github.com/reduxjs/redux/issues/992#issuecomment-167964652
const typedActionToPlain = (store: any) => (next: any) => (action: any) => {
next(Object.assign({}, action));
};
export default typedActionToPlain;
Pay attention not to step into the toe of Thunk middleware when registering it:
const rootStore = createStore(rootReducer,
applyMiddleware(thunkMiddleware,
typedActionToPlain //this must be after thunk, otherwise it will try to convert an async function to a plain object
)
);