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