TS is certainly excessively powerful though.
It may seem that any definition is final, but none is. Since the last definition of a struct field overwrites a previous one, the order in which e.g. files are interpreted matters. It's like writing a config by using Python dicts, with the added complication that creation of a new one and updating of an existing one are indistinguishable.
This may be okay in practice, given some discipline.
You can have wider types being overridden by more closed types. e.g. string => "this literal". But you cant have two disagreeing values.
I use this to create kubernetes manifests at work, at a reasonably large scale. The inability to join multiple files without fear of collision is specifically one of the best features.
Edit: I'm struggling to see where it fits in the whole k8s ecosystem.
Then I have a tool file that loops through that and renders it into fall files. Then argocd picks that up in chunks with application files.
Its awesome cause it lets me set project wide defaults and restrictions. It also lets me do stuff like. "If there is at least one manifest called x create an argocd application for it automatically" or " loop through these repos and create an app for each one with the following properties"
This in turn requires additional tooling to catch errors early, and also means that a starlark-repl for Bazel will never really be all that useful, since the build graph doesn't exist in starlark alone.
In my experience, this makes Bazel a significantly harder build system to truly grok, tho perhaps easier to use it without understanding it.
Contrast with nix, where the entire build graph exists as a nix expression. In my experience, you can gain a surprisingly deep understanding of nix armed only with knowledge of nix-the-language (and without knowing any implementation details of nix-the-binary-that-builds-derivations).
Tried a lot of them, and after a while I found the nix the package manager on non NixOS requires too many workarounds. Things don't just work. For example, installing alacritty requires an OpenGL wrapper. Neovim can't find libraries to build some plugins. Basically, anything GUI had issues.
In the end, `cargo install`, `go install` and download a release archive from github are simpler to script for most of the tools I use.
The people I want to help are those who are unknowingly reviewing malicious commits, and I think that declarative configuration languages have a part to play there.
Since part of the sales pitch of using a general lang is emphasis on code reuse, it rings kind of hollow for me there, and here too.
In my opinion the issue with Nix is that the data model is not crisply defined -- it's there, but hidden under a lot of goop that is the Nix language itself and the various assumptions and baggage that goes with it.
What I want is a primarily declarative syntax supporting a rich set of data structures, ideally a non-Turing set of primitives, with a much more intuitive way of gluing things together. So basically bash (or even sh) with a well-defined way of transmitting environment variables and setting up the environment.
The idea of importing a language that has broader support (typescript) as an alternative to the Nix language seems appealing at first, but typescript is such a high-dependency system that it's hard to get excited about it.