With Nix, you can programmatically describe an installation of packages (including how they're built). This then allows having multiple versions of the same package installed, easily patch (or vary build arguments) of package dependencies, an easy way to distribute or install these same sets of packages in whatever distribution of Linux (or on macOS), development shells which load the required build tools, a saner build language than Dockerfile's. With NixOS, the configuration of services can be managed from a single source.
I think for any particular task, it's more difficult to bother with Nix compared to just using some convenient solution. (e.g. using Dockerfiles to build Docker images, or using cloud-init to configure a VM setup). -- So, it's harder to say "is Nix better than <this> for <this problem>?".
Compared to other package managers: You could use Nix to install packages, in the same way you would with other package managers. An advantage to this is you'll get the same version of the package regardless of which distribution you use. (Whereas with, say, Ubuntu you might need to add a PPA to get versions as bleeding-edge as what Arch would offer).
Nix's tooling is also broader in scope:
e.g. with nix-shell, you can have a shell which has a Go-lang compiler (or whatever) in that shell, but without needing the Go-lang compiler installed on the computer. This is comparable to e.g. asdf, or to running your toolchain in a Docker container (like what VSCode Remote Containers offers). -- i.e. Nix can be useful for development.
NixOS takes the same Nix declarative language, and allows describing the configuration of the whole OS setup with it. Just as Terraform declares an orchestration of cloud infrastructure, NixOS allows declaring how the OS is setup. (Here, Nix is comparable to e.g. cloud-init or Ansible). -- i.e. Nix can be useful for deployment.