It’s literally impossible to write clean code which compiles to clean code with Angular.
Zone locals also allow you to maintain "task-specific" state, for instance allowing you to access the current request being processed without it being passed around. Another use case is having your logger show context information- Frameworks like RoR have done this forever- they show the request ID on each log message that results from processing that request. I don't think there's any good way short of passing the logger around everywhere to pull that off in Javascript short of using Zones.
What it does to Promise and other parts is definitely an annoyance, but the benefits you get for it are a lot. If Zones were a standard part of the JS runtime none of that "patch the world" would be needed, as the JS runtime would support it out the gate. Zone.js was always meant to be a polyfill of the Zone concept on the way to standardization. It is unfortunate that standardization has failed because I think it's a very useful idea and there isn't any real alternative to achieve the same goals.