Elixir's heavy reliance on pattern matching has always made it kind of "dynamic language where you still have to think about types" vibe to it. It's also always had a spec meta-language (taken from Erlang) which a lot of people use. You should read up on how they have been implementing the type system, it's pretty interesting! I would not say it's "bolted on." It also has full inference so all codebases get the benefit of it whether you specify types or not.