Type Specifications & Dialyzer
any(), term(), none(), no_return(), atom(), boolean(), integer(), pos_integer(), neg_integer(), non_neg_integer(), float(), number(), binary(), bitstring(), string(), nonempty_string(), unicode:chardata(), iolist(), iodata(), list(T), [T], nonempty_list(T),…
19.1 Types and specs
-module(shapes).
-export([area/1]).
-export_type([shape/0]).
-type shape() :: {circle, Radius :: number()}
| {rect, W :: number(), H :: number()}.
-type result(T) :: {ok, T} | {error, term()}.
-opaque handle() :: reference().
-spec area(shape()) -> float().
area({circle, R}) -> math:pi() * R * R;
area({rect, W, H}) -> float(W * H).
-spec safe_div(number(), number()) -> result(float()).
safe_div(_, 0) -> {error, zero};
safe_div(A, B) -> {ok, A / B}.19.2 Built-in types
any(), term(), none(), no_return(), atom(), boolean(), integer(), pos_integer(), neg_integer(), non_neg_integer(), float(), number(), binary(), bitstring(), string(), nonempty_string(), unicode:chardata(), iolist(), iodata(), list(T), [T], nonempty_list(T), maybe_improper_list(), tuple(), {T1, T2}, map(), #{key := T, optional => T}, #{atom() => T}, fun(), fun((A) -> B), pid(), port(), reference(), node(), module(), mfa(), timeout(), char(), byte(), arity(), 1..10, literal atoms/ints, unions with |, dynamic() (OTP 26+ gradual typing).
Record field types:
Callback specs for behaviours:
-record(user, {id :: integer(), name = "" :: string(), tags = [] :: [atom()]}).
-type user() :: #user{}.-callback init(Args :: term()) -> {ok, State :: term()} | {error, term()}.
-optional_callbacks([terminate/1]).19.3 Dialyzer
Finds type discrepancies, unreachable code, wrong calls — based on success typings (no false positives in theory).
Typical warnings: "Function has no local return", "The call ... will never return since ...", "Guard test can never succeed", spec mismatches.
eqWAlizer (WhatsApp) is a stricter type checker for Erlang, integrated with ELP.
rebar3 dialyzer
# or manually:
dialyzer --build_plt --apps erts kernel stdlib
dialyzer -r ebin