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 ) );