I'm glad you found great uses for clojure.spec. We need more tools like it.
If you ever find yourself writing TypeScript I'd recommend you try io-ts, which fullfills the same role as clojure.spec but is also able to auto-generate types from the runtime codecs, which you can then use in your functions to make sure they are only used with data that passed decoding. Not having to rely on discipline or "pinky promising" that you have decoded data is a huge boon when changing code later, or understanding the full scope of a function.
This isn't unique of course to Clojure or TypeScript as you mentioned, but there aren't too many good libraries built on the concept, and it doesn't work well in all languages.
> How the heck do you achieve code re-use between completely incompatible ecosystems - in our case, JVM and Javascript?
Just to point it out, Clojure does this the same as everyone else and has the same issue: So long as you don't call runtime-specific non-portable functionality, you should be good. Plenty of Clojure libraries targeting the JVM do not work on ClojureScript and viceversa.
> Clojure has an excellent price/quality ratio for building software
I agree that Clojure is fairly competitive, so long as we're talking initially building software. I just find it that specially once maintenance, rapid requirement changes, junior engineers, and staff rotation is taken into account, either developer productivity or the robustness of the software falls off a cliff.