> For example, in your second link, one of the functions expects a 'complex' instance DispatchProps which has a method toggleOn... This abstraction doesn't make sense conceptually. What is a DispatchProps? It doesn't adhere to Alan Kay's notion of a 'message', it's clearly a structure (it's a complex one because it exposes a method). Components should communicate to each other via messages, not structures.

the `mapDispatchToProps` idea has been in `react-redux` since the very beginning. I don't understand what are you complaining about here. If you prefer, you can ignore this practice and pass the whole dispatch function to the component, and then call `dispatch(actionCreator(params))` directly. Typescript won't get in the way of you doing that.

> Also, the method builder.addMatcher(...) accepts a function as an argument - It doesn't seem like an ideal abstraction either. Functions are not messages.

The addMatcher API is not concerned with sending messages, it is concerned with receiving them. You are specifying what should happen when a certain message type arrives. Hence it seems normal to me to specify that as a function that given the message does some stuff. Since these are reducers, the "does some stuff" part is: given a previous state and an action of type X, compute and return the new state Y.

> Also, the thunkSendMessage function signature is very complex; the return type is highly convoluted. That's definitely not a message.

Of course not. It is a function that sends some kind of message after asynchronously calling some API and getting its response, or another kind of message if the API call failed. That's what the complex type says. The usefulness of thunks is that you do have this notion of "ongoing asynchronous process that may succeed or fail" explicitly represented (so you can for instance cancel it), which you'll have a much harder time if you want to represent by using just actions and reducers.

> You can already see the complexity seeping into the interfaces. Just a few years of TypeScript is distorting the original philosophy. I remember Dan Abramov was very careful about what to pass into functions and what to return from them and made it a point to encourage cloning objects using the ... spread operator.

I think you are misremembering some things here. Dan Abramov used to advocate for a strict separation between presentational and container components [1], including the use of `connect` in exactly the same fashion you are criticizing in your first point.

Likewise, cloning objects using the spread operator was never a goal in and of itself. Dan advocated for it as an easier way to avoid mutating the state. Not mutating the state was the point here. Redux-toolkit accomplishes this point by using immer, a library that conceptually gives you a copy of the state so you can just mutate and return that instead (with the advantage that non-modified parts are not cloned).

Also, you can just not use that and return spread-operator-cloned objects from your reducer functions instead. Everything will keep working normally (and passing the type checks) in that case.

[1] https://medium.com/@dan_abramov/smart-and-dumb-components-7c...

PS: Thanks for your work Mark!