"almost never" and "simply use externs file (which you may or may not need to write yourself)" does underpin my point that you have to take care. I'm not saying it is necessarily difficult or takes a long time to get right, but it does require that someone makes sure everything survives the advanced opts compilation.
This has burned me on a past cljs project, it's not even a concern on my Elm projects.
I would say that Elm lets me refactor front-end code fearlessly. I can confidently rewrite abstractions that are so fundamental that I'd be stuck with them forever in a dynamically-typed language because the rewrite would be so much more costly.
It reminds me of when people say that Mongo is better than Postgres for prototyping because it doesn't have a schema. In my experience, the very concept of having explicit schema transformation as the schema changes is why I'd consider Postgres to be better for prototyping: it's precisely the time when your schema is changing the most.
Of course, if we could unanimously agree on these trade-offs, then we would all be using the same stack and there would be no dynamic vs static typing debates.
I still use Clojure as a backend language (I'll never give up Datomic) and while writing code in Clojure is usually faster, I spend much, much more time in debugging, often because of type errors, and especially after re-factoring. In Elm I spend more time up front, but less time overall.
I've been writing Clojure for six years now, Elm for three. There are definitely usecases where I'd pick Clojure(Script) over Elm, but for those usecases where it doesn't matter which of those you pick, I'd choose Elm any day of the week.
This is not to say Clojure(Script) is bad. In my opinion, Clojure and Elm are the best languages around.