Elixir v1.20 Evolves into a Gradually Typed Language
Elixir v1.20 is officially released. A set-theoretic type system, developed since 2022, enables gradual type checking for entire programs without type annotations, making it highly effective for identifying dead code and verified bugs.
The official Elixir blog announced the release of version 1.20 on June 3, 2026. The most notable feature of this release is the evolution of Elixir into a “gradually typed language.” This advancement allows type inference and gradual type checking to be applied across all Elixir programs without requiring type annotations. As a result, developers can identify dead code and type mismatches that would inevitably fail at runtime (verified bugs) without additional workload.
Background of the Type System Introduction
The Elixir core team first announced their initiative to incorporate set-theoretic types into Elixir in 2022. By June 2023, a research paper on this type system design had gained international recognition and received awards. At that time, the project officially transitioned from the research phase to development. The release of v1.20 marks the achievement of its first development milestone.
According to the announcement on the official Elixir blog, three primary goals were set for the type system. The first is “soundness”—ensuring that the types inferred and assigned by the type system align with the actual behavior of the program. The second is “gradual typing”—the introduction of a dynamic() type that allows the type system to handle variables or expressions checked at runtime. Unless the dynamic() type is explicitly used, Elixir’s type system behaves as a static one. The third goal is “developer-friendliness”—to enable the use of basic set operations such as unions, intersections, and negations to define and implement types, while also providing clear error messages.
The Role of the dynamic() Type
Many gradually typed languages feature an any() type, which is a permissive type that does not report type violations. Elixir, however, adopts a dynamic() type as part of its gradual typing system. This type has two key properties: compatibility and narrowing.
Consider the following example:
def process(value) do
# The type of 'value' is not determined
value + 1
end
In traditional gradually typed systems, since it cannot be determined whether value is an integer, the type system either flags a type violation or ignores it by treating value as an any() type. Elixir’s dynamic() type, on the other hand, prevents the type system from raising unnecessary alarms (false positives) while actively narrowing the type where sufficient information is available to detect bugs. This unique approach allows Elixir’s gradual type system to provide value to existing dynamically typed code without requiring developers to add type annotations.
Detecting Verified Bugs and Benchmark Performance
One of the standout features of Elixir v1.20’s type system is its extremely low false positive rate when applied to existing programs. Any violations reported by the type system are guaranteed to “fail at runtime,” which makes them “verified bugs.” Additionally, the system is capable of detecting dead code.
The official announcement highlighted Elixir’s performance on a benchmark called “If T: Benchmark for Type Narrowing.” This benchmark evaluates the precision of type narrowing, and Elixir achieved a passing grade in 12 out of 13 categories. This demonstrates the system’s ability to accurately recover type information from typical Elixir code.
Partnerships and Sponsorship
The realization of this type system was significantly supported by a partnership with CNRS (French National Centre for Scientific Research) and Remote. The current development efforts are being sponsored by Fresha and Tidewave.
Future Prospects
Version 1.20 represents only the first stage, focusing on “gradual type checking without requiring type annotations.” Future milestones are expected to include the introduction of type annotations and the expansion of more advanced type inference capabilities. As Elixir’s type system matures, it could bring transformative changes to the ecosystem, enhancing both developer productivity and code quality.
In software development, there is often a trade-off between adding new features and ensuring type safety. With this release, the Elixir team has struck a delicate balance. The ability to benefit from type checking without altering existing codebases is particularly promising for large-scale projects.
Editorial Perspective
Short-Term Impact With this release, the Elixir community is expected to adopt type checking for existing codebases. Projects that previously hesitated to adopt types due to high implementation costs may now find it easier to experiment with gradual type checking. In the next three to six months, it is likely that more projects will incorporate “type-checking CI” into their quality control processes. Additionally, the low false positive rate will be a critical factor in encouraging adoption in practical applications.
Long-Term Outlook The adoption of a set-theoretic type system has the potential to elevate Elixir into a more robust language. It may also influence other programming languages. While gradual typing is not a new concept, Elixir’s approach of providing value to existing dynamically typed code “without requiring type annotations” sets it apart from languages like TypeScript and Python with tools such as mypy. Over the next one to three years, Elixir could emerge as a strong contender for new projects prioritizing type safety. However, challenges such as increased compilation time due to type checking and the potential refactoring workload required to satisfy checks may surface in practical use cases.
Questions from the Editorial Team Does gradual type checking without requiring type annotations truly “not increase the developer’s workload”? While fixing violations reported by the type system might be less burdensome than adding annotations to existing code, it is not entirely effortless. Moreover, how practical is the expressiveness of a set-theoretic type system compared to statically typed languages? The ultimate test of whether Elixir’s type system is truly “sound” will be its performance in real-world applications. We encourage readers to try implementing this type checking in their existing Elixir projects and share their experiences.
References
- Elixir v1.20 released: now a gradually typed language - Official Elixir Blog — Published on 2026-06-03
- Research Paper on Elixir’s Type System (2023) - Related Information — Published on 2023-06-22
Frequently Asked Questions
- Does Elixir v1.20's type system require type annotations for all code?
- No. The gradual type checking in v1.20 works even without type annotations. It performs type inference on existing dynamically typed code to identify dead code and verified bugs. Type annotations are expected to be introduced in future milestones.
- What is the difference between the `dynamic()` type and the `any()` type?
- The `any()` type permits "anything" and does not report type violations, whereas the `dynamic()` type has the dual properties of compatibility and narrowing. It behaves flexibly in areas with insufficient information but actively narrows types and detects bugs where sufficient information exists. It minimizes false positives while reporting only bugs guaranteed to cause failures.
- How was Elixir v1.20's type system evaluated in benchmarks?
- It was assessed using the "If T: Benchmark for Type Narrowing," which evaluates the precision of type narrowing. Elixir passed in 12 out of 13 categories, demonstrating its capability to accurately infer type information from standard Elixir code.
Comments