Yes the solution you describe is what most people seem to be suggesting and I agree it gives a good balance of maintainability and safety. It has even been written up as a pattern here. I think there are still problems with it though. Firstly, it introduces a level of coupling between the layers of your app which is a bit distasteful. Secondly it implies that all state is either owned by _me_ or at the root level. I may have state that is owned by some intermediate component too. In that scenario, it seems I need _another_ derived model:
update: Msg -> RootState -> MiddleState -> Model -> ...
So again, it could get messy.
I still agree that it is the best practical solution but still don’t feel entirely happy with it.