The problem really stems from how tightly entangled packages are to the nixpkgs source tree. Nix offers the most foundationally modular system possible, and it organizes its packages in a monolithic source tree! This means that despite installed packages being totally isolated in the /nix/store/, the package source (what Nix calls a "derivation") is semantically tied to whatever specific dependency version was implemented in the contemporary nixpkgs source. If you want to provide users more than one version of a package inside the same source tree, you must put the version in the name, like SDL2 or python3.11.
I started this GitHub issue a long time ago: https://github.com/NixOS/nixpkgs/issues/93327. Somewhere buried inside may lie the answer to your question. Either way, I have mostly given up on wrapping my head around the current ecosystem of half-baked solutions to this mess; despite still actively using NixOS in ignorance.
This only works for versions of your package that do exist in nixpkgs but aren’t currently the default for your chosen channel, so it doesn’t help if your channel is out of date and you want to install a newer version that hasn’t been packaged yet. But then that’s the case in almost any Linux distro if you rely on installing your software from the distro’s native package repo, and much the same solutions exist in NixOS as in other distros. Although if you’re really determined, you can also start writing your own derivations to automate building the latest versions of your favourite applications before they’re available from nixpkgs…
¹ https://lazamar.co.uk/nix-versions/
² https://lazamar.github.io/download-specific-package-version-...