Typing in Elixir
Elixir is dynamically typed, but not “untyped.” Values have types at runtime, and the language gives you several ways to document, constrain, dispatch on, and check those types.
Runtime values are typed. Variables are not statically typed. Function contracts are usually expressed through pattern matching, guards, structs, typespecs, behaviours, and protocols.
Elixir’s official site describes it as a “dynamic, functional language” running on the Erlang VM (the BEAM).
Built-in Types
Section titled “Built-in Types”Elixir has several built-in types that you can use to define the type of a value.
:ok # atom42 # integer3.14 # float"hello" # binary / string'hello' # charlist[1, 2, 3] # list{1, 2} # tuple%{name: "Owais"} # mapfn x -> x + 1 end # functionpid # process idStructs
Section titled “Structs”A struct is a map with a named shape. Under the hood, they have a __struct__
field that stores the struct’s name.
Pattern Matching
Section titled “Pattern Matching”You model data with tagged tuples, maps, and structs, then branch by shape, as Elixir uses shape-based pattern matching.
Guards
Section titled “Guards”Guards are expressions that are evaluated at runtime to determine if a pattern matches. They can be used in pattern matching to constrain the values that can be matched.
Common helpers:
is_atom/1is_binary/1is_boolean/1is_float/1is_function/1is_integer/1is_list/1is_map/1is_number/1is_tuple/1Typespecs
Section titled “Typespecs”Typespecs are annotations1 used to specify the type of a function’s arguments and return value. They’re not enforced by the compiler, but for documentation and static analysis tools like Dialyzer.
Behaviour & Protocols
Section titled “Behaviour & Protocols”Behaviours are interface-like contracts. They define callback contracts that modules can implement.
Protocols provide type-based polymorphism, by defining behaviors that can vary by data type.
Gradual Set-Theoretic Types
Section titled “Gradual Set-Theoretic Types”This is a part of an ongoing effort2 to introduce type-checking to the Elixir compiler.
- Gradual typing - You can keep writing normal dynamic Elixir. The type system is introduced incrementally and does not require rewriting the ecosystem.
- Set-theoretic typing - A type is treated as a set of possible values. Type operations work like set operations: union, intersection, and difference/negation.
Footnotes
Section titled “Footnotes”-
Typespecs Reference — Elixir v1.19.0-Rc.0. https://elixir.hexdocs.pm/1.19.0-rc.0/typespecs.html. Accessed 31 May 2026. ↩
-
Gradual Set-Theoretic Types — Elixir v1.19.5. https://elixir.hexdocs.pm/gradual-set-theoretic-types.html. Accessed 31 May 2026. ↩