
Elixir v1.20 ships gradual type checking without type annotations
Elixir v1.20 completes the first milestone of the language's set-theoretic type system: type inference and gradual type checking for every program, with no annotations and, the team says, a very low rate of false positives.
Elixir v1.20 was released on June 3, 2026, and marks the first development milestone of the language's set-theoretic type system. Announced in 2022 and followed in June 2023 by an award-winning paper on the design, the effort has now moved from research into the compiler: every Elixir program is type inferred and gradually type checked, without developers writing a single annotation.
Verified bugs and dead code
The goal is to report dead code and "verified bugs" — typing violations guaranteed to fail at runtime if executed — without adding developer overhead. According to the release post, Elixir's implementation passes 12 of the 13 categories of the "If T: Benchmark for Type Narrowing". The type system was made possible by a partnership between CNRS and Remote, with development sponsored by Fresha and Tidewave.
The dynamic() type: compatibility and narrowing
Where many gradual systems use any() to mean "anything goes", Elixir introduces dynamic(), which has two properties. Compatibility means a violation is reported only when the supplied and accepted types are disjoint: a variable inferred as dynamic(integer() or binary()) may still be passed to an operator that expects numbers. Narrowing makes the type behave like a range: using data.a and data.b refines a value to %{..., a: number(), b: number()}, so writing data.a + data afterwards is flagged. Guards are typed too — is_list/is_integer infer unions, is_map_key(x, :foo) and its negation infer the presence or absence of a key, and tuple_size(x) < 3 turns elem(x, 3) into a violation. In case expressions, matching nil in an earlier clause refines later clauses to binary(), which also surfaces redundant clauses and dead code.
Faster compiles and what comes next
The release also improves compilation times, especially on many-core machines; in the team's synthetic benchmarks, Elixir's build tool is now the fastest for the common "compile + boot + test" lifecycle. A new :module_definition option can be set to :compiled (the default) or :interpreted through elixirc_options in mix.exs; it changes only how the contents of defmodule are executed and does not affect the .beam files written to disk. Type signatures remain ahead: the team says it will introduce them only once it is satisfied with the type system's performance and can implement recursive types, parametric types and the traversal of map key-value pairs as an enumerable efficiently.
SiTech — AI-powered web development
We build fast, modern websites and bring AI into real business workflows. Have a project or a question? We'd love to help.