How do typespecs / dialyzer compare to Typescript?

I’m a big fan of typescript as a way to introduce sanity / ergonomics into JavaScript and love these features:

  • Very good type inference
  • Parameter documentation
  • Intellisense / Language Servers

I’m not sophisticated enough with types / category theory to fully understand why better type systems make better guarantees but those basics seem like very strong wins.

I’m not familiar with the “success typing” of dialyzer - but does it provide similar benefits as those above or is it trying to do accomplish something different?

1 Like

Dialyzer is a good tool to provide type bug… but Elixir is not strongly typed. There were some attempts to add type system, but it’s hard when dealing with messages.

BTW there is this new presentation on dialyxir…

There is MLElixir and LFE (Lisp Flavoured Erlang) if You are up to try.

There is Elixir language server for the last points.

1 Like

It isn’t statically typed (as it’s dynamically typed), but AFAIK both erlang and elixir are strongly typed? https://en.wikipedia.org/wiki/Strong_and_weak_typing

3 Likes

Yes, It should be strong :slight_smile:

1 Like

Dialyxir/dialyzer by itself is quite frankly terrible in terms of ergonomics. The plts take forever to load, the messages are cryptic, and it kind of makes me not want to use it.

However, the elixir_ls plugin for vscode, which dialyzes in the background, is completely game-changing, and I basically type everything as I go along now. It’s caught loads of errors, makes my code more tight, and makes me think about what I’m doing along the way.

5 Likes

The plts get cached, so the first time it might take around 5…10min, but then it’s usually very fast for me, a few seconds, a bit more if deps changed.

Dialyxir output got much more friendly now, so far it helped me catch a lot of issues, it ensures good typespecs, and you can always ignore what doesn’t make sense. Dialyxir’s README is worth the read.

1 Like

these are just my opinions:

“Ignoring what doesn’t make sense” is a bit of problem from the command line, because a lot of cruft builds up and it becomes a pain to roll back through a lot of things to find what you need… As a result i personally found that the time I call upon dialyxir the most is “because I done something royally bad and save me static typing you’re my only hope” - by that point I’ve tried a lot of things like nuke and reload deps, and I couldn’t trivially make dialyxir a part of my CI workflow for the same reasons, so PLT caching didn’t help.

Having your editor actively run static typing on file save, and static typing code hints and highlighting is night and day to triggering it on the command line. Also, at least for elixir_ls, the PLT process is done automatically, and, in the background, so you can still be productive while it’s going on.

Yes, a lot of these things can be ameliorated by having a bit of discipline, but I do think that ergonomics are important. I’m an old dog and teaching me new tricks is hard.

bless whoever wrote elixir_ls, because it got me to static type my code.

Yeah, things can definitely improve. I hope gradualizer will become soon a better tool than dialyzer.

Btw I also use elixir-ls (through emacs), type checking on file save helps a lot with the develop flow, but to run for the whole codebase, locally or CI, dialyxir CLI with zero errors is an important metric I try to keep (mix dialyzer --halt-exit-status).

Picking good flags helps reduce useless warnings. This is the base set I use: [:error_handling, :race_conditions, :unmatched_returns, :underspecs]

Eventually I need to force ignore a few dialyzer errors, no more than 5 ignores configured per project, because of dependency issues, or even elixir.

For OSS, travis helps with caching, so dialyzer takes a minute. In Jenkins I couldn’t find a way to do it easily, but the dialyzer job runs in around 10min. Using plt_add_deps: :apps_direct,, and adding apps needed manually under plt_add_apps makes build time reduce much more than the default.

3 Likes