Add in dialyzer and you have something that gives you the flexibility loose typing and a fair amount of the guarantees of a more formal type system.
And with Elixir you have a way of starting processes again should you still crash with an error.
Never mind that microservices and cross node messaging are built in as standard, as well as confidence in being able to scale your system with things like Flow or OTP.
I'm surprised not to see more traction (especially in startups) and I love a project this complex only has 16 bugs on github!
static typing is somewhat of a programming religious wars. I mean sure, extremely weak typing is IMO horrible (python, ruby, js, I'm looking at you) but being dynamic does mean that quickly testing out an alternative code path. Just today I realized I needed to forward some information to a somewhat polymorphic data structure, a process which I hadn't planned for, I found a map structure that is encapsulated state in a gen_server in exactly the right place, so I just shoved it into the map under a new key. That is effectively breaking what could have been a static type system. And it was two lines of elegant code, no refactoring necessary, and probably a line of documentation saying that in this corner case the structure will contain this extra info.
IMO the right approach is compromise. You could do this in a statically typed system by just making everything a map... which is effectively what the BEAM languages do, but at least there's a type analysis tool that can introspect deep into the built in "flexible" types.
Ruby: duck, dynamic, strong.
Python: dynamic, strong.
JavaScript: dynamic, duck, weak.
Elixir: dynamic, strong.
https://wiki.python.org/moin/Why%20is%20Python%20a%20dynamic...
In the end a lot of your crashes are going to be "other people's software, like, say, "an unexpected race condition in nfs". Or "some other library crashes when parsing a really big json".
In the end these are not really solved by a static type system. The idea that static types will save you is flawed by giving you a false sense of security and tying up developer time outside of the 80-20 Pareto law... In my short so far experience as an elixir developer I've delivered all of my products on time. Running it I know there are errors since they floated by the console in the background... I didn't care about the 1% error since it did not significantly affect my performance. Not worrying about every last problem has been great for my sanity.
Finally, there is a possibily antipattern Dev cycle, I've settled in to. Unit test the happy path, write happy path, conjure errors, unit test them, solve them with an eye for recovery, spec out the type system, sweep away last lingering errors with dialyzer. Occasionally totally refactor.
I can usually demo any time after step 2.