Direnv can automatically load an environment when you enter a directory, so it automatically "opens" virtualenvs/nix shells/etc. The Emacs direnv mode ensures that each buffer sees the direnv mode for its project directory.
I've found this to be a great compromise between automatic behavior on the one hand and transparency + control on the other—I get the right environment loaded automatically very consistently and, if something goes wrong, I can open a shell and poke around to see what's going on (is my nix shell messed up? is the right tool not loaded via direnv? etc). The only time I need to do anything manually is if I make a change to the environment and need to update Emacs about it, in which case I just run M-x direnv-update-environment.
Once I got this set up, I can just rely on executable-find to check for (and find) exactly the right tool on a per-project basis—no more worrying about global or seeing the wrong version of a tool. This also made it easy to do stuff like only run formatting if the corresponding tool is available: I add hooks to various programming language modes that only turn on lsp/formatting/etc if executable-find sees the corresponding executable.
Compared to the hassle I've had to go through helping my colleagues debug VSCode not seeing the right conda environment, virtualenv or the right version of various tools, Emacs + direnv has been a far nicer and more consistent experience.
[1]: https://direnv.net/
I use VS code for a couple days and I will already want to go back to Emacs, and having a good LSP experience is pretty important for either.
lsp-mode pretty much seems to do the right thing for Typescript projects without any configuration. At work we use React/TSX, for personal projects I use Svelte, and Emacs can find all the symbols, provide correct completions, and point out obvious mistakes. My only complaint is that I can never get Emacs's indentation to match what Prettier wants to do, so I'll type a bunch of code, prettier-on-save, and everything gets moved around. Not a big deal, but something I'd look into more deeply if I actually did Typescript full time. (I just occasionally change frontend stuff, but mostly program Go. gofmt and Emacs agree on formatting, but I think that's because Go is opinionated about formatting and so it's easier for multiple tools to have the same opinion. With Typescript, anything goes.)
TL;DR: despite the eglot marketing campaign and its overall cleaner design, lsp-mode might be the thing for you. I try eglot every 6 months and always switch back to lsp-mode. It has its quirks and WTFs, but doesn't get in my way too much.
I had this same issue, and it was annoying enough I continued to use https://github.com/editorconfig/editorconfig-emacs alongside prettier.
This does create another annoyance in having to configure editorconfig for new projects instead of relying on prettier alone.