It is correct to say that dynamic linking with rebuild-on-input-dependency-change (like NixOS does) is similar to static linking when it comes to rebuild behaviour.
However, also remember that changing dynamic libraries behind executables back is a concept that only makes sense in the presence of ABI compatibility. This is predominantly a C concept (or at least popular in the C world), and much less so for other linked programming languages like C++, Haskell, Go, and so on. Thus Nix being a general-purpose build system takes the general route here, and builds can also use their dependencies during the build step (e.g. a packaged program's autoconf suite might check the version or a symbol provided by a library), which requires full rebuilds for reproducibility.
(Nix is working on content-addressed instead of input-hash-haddressed builds, which might open the door for avoiding many rebuilds that do not affect build _output_.)
That said, it might still be quite easy to achieve what you want:
* If you want to iterate on a C library that's early in the dependency graph, in am ABI-compatible fashion, you coul duse LD_LIBRARY_PATH or LD_PRELOAD on it.
* If you want to override libc in an ABI-compatible way, you can use `patchelf` with its `--set-interpreter` and `--set-rpath` flags to replace the libc an executable is linked against after the fact. For example, you can make an `.override` of a nix derivation that just `cp -r`'s the existing files, and then calls `patchelf` on them.
I have used both these methods to work around glibc bugs that I patched out, avoiding even to have to recompile my own software at the top of the build dependency tree.
Some more relevant links about replacing glibc specifically:
* https://github.com/NixOS/nixpkgs/issues/50329
* https://github.com/NixOS/nixpkgs/issues/129595
If you want to replace things system-wide instead of for your own software, the `system.replaceRuntimeDependencies` mentioned by a sibling comment might be a good choice.