Dialyzer is indeed a pain in the ass, but what is not a pain in the ass is vscode's elixir_ls plugin which incrementally dialyzes and gently nudges you into making static type declarations (your code shows up uglier when you don't do it).
Life changing. It's stopped me from pushing runtime errors probably about 20 times now, in the last few weeks that i've been using it. At this point I'd say that it's strong enough to close 95% of the difference between static and dynamic typing.
Elixir's (maybe going to be merged into the standard library) property checking semantics (ExUnitProperty and StreamData) are quite amazing and super easy[0], and will catch whole classes of things that your compiler won't so I would strongly suggest checking out Elixir now.
[0] today I implemented in an hour a property check that makes me confident that a mathematical algorithm that I implemented for a fuzzer is ok (my first attempt was wrong), and then a property check that demonstrated that that algorithm applied to a stateful set of events doesn't violate critical invariants.
Also, you will almost certainly never get a statically typed Elixir, because it makes a lot of things like hot updates hard or inelegant. Sending interprocess/internode messages is something could be extremely intolerant to a static type system, because, in a way you're breaching the purity of the functional paradigm (it's the BEAM language's "one big lie"). Go struggles with this a lot in its channel semantic, and it's why there is a ton of boilerplate in gRPC (and almost no boiler plate in erlang RPC).
Also gently breaching the type system is incredibly useful in mock tests - for example, in my current project I do about 60 high-load end-to-end tests in parallel with clones of my central scheduling algorithm - this is possible because my test suite reaches into the main body, dynamically creates a new scheduler, and appends that information into an HTTP request, which is passed into a "plain old map" and intercepted only in test environment. This not only greatly accelerates the end-to-end tests (I run the full suite as a matter of course before each commit) but it also gives me confidence that my system will run under a load that is greater than I can manually trigger.