Every legacy codebase I have worked with was actually a successful business. That probably plays a big role in why I enjoy working with them. The job is not easy, and in one case (800kLOC of PHP without a single function), I had to rewrite everything from scratch.
Legacy JS with its strata upon strata of framework du jour and jquery and porous language are indeed notoriously annoying. To be fair, I just isolate the legacy JS to its own little DOM sections, and then introduce a new framework in parallel until I can nuke the old code out.
Revamping a legacy JS codebase often comes with a design revamp as well, so it often becomes a matter of strangling [1] out the old API. I do really enjoy how typescript allows me to gradually introduce typing and leverage static analysis for more adventurous refactoring.
I use golang, rust and typescript as my daily drivers lately, but I must admit that my most horrendous legacy codebase experience was a tiny 20kLOC go program that was just a mess of concurrency nonsense. PHP codebases have a certain "flatten it out and don't be clever" style to them that make for easy strangling [1]. Highly abstracted codebases where the abstraction doesn't fit the use case anymore, or the abstraction was thoroughly eroded by generations of misinformed developers are much trickier.
What language I would use to greenfield a new application would depend highly on the experience of the team, but my usual approach is "whatever we are already using".
[1]: https://www.redhat.com/architect/pros-and-cons-strangler-arc....