Understanding @spec in Elixir and Seeking Recommendations for IDE Tools

As I delve deeper into Elixir, I’m fascinated by its powerful features. However, there are a couple of areas where I could use some help, and I was hoping you all could shed some light on them.

Firstly, I would like to learn more about the “@spec” in Elixir. While I have some basic understanding of it, I’d love to get a clearer picture of how it works and its best practices. Any insights or examples you can share would be greatly appreciated!

One thing I really enjoyed when working with TypeScript was its ability to alert me to potential issues at the code level, especially when line numbers weren’t helpful. This feature saved me a lot of debugging time. Now, my question is: does Elixir offer similar capabilities? Are there any IDE tools you recommend that provide these features to enhance the development experience?

Moreover, I’ve noticed that Elixir has a few “gotchas,” particularly when dealing with atomic keys vs. string keys, which can lead to those annoying little bugs that are easy to overlook. I’m curious if there are specific tools or techniques available in the Elixir ecosystem that can catch these issues at the code level, making it easier to address them proactively.

I’m eager to improve my Elixir development workflow and write more robust code. So, any tips, recommendations, or personal experiences you can share would be greatly appreciated!

Thank you all in advance for your support and insights. Looking forward to some engaging discussions!


Hello and welcome to the forums.

In short, Elixir is maybe probably getting a type system but as it stands it does not have one. You can use Dialyzer, via the Dialyxir package, to do type checking with @specs. I personally don’t have much experience with it so can’t give you any pointers here, but I believe it can help with the atom/string key situation (eg, @spec foo(%{atom() => any()}) :: any()). Otherwise context is usually helpful for knowing what they will be. In short, it will pretty much almost always be atom keys unless the data is being parsed blindly from an untrusted source. In this case they will be (at least they should be) string keys as dynamically creating atoms is a big no-no: any on BEAM instance can only define a finite number of atoms an when it runs out, bad things happens. Often untrusted data will be cast into a known shape in which case the keys are generally converted to known atoms—Ecto does this, for example.


ElixirLS does a decent job of suggesting spec sections based on Dialyzer inference. I don’t know if Lexical or NextLS support that yet but I don’t see it listed. You do have to tweak them at times to be really precise but they’re a great starting point. You can also add dialyzer checks to your CI builds or run it as a mix task. I can’t remember because I squash them early but dialyzer warnings show in VSCode I think both in-line and in the problems section if you wanted them out of the way.

Elixir is still a dynamic language at the end of the day.

1 Like