Nominal types are new in Erlang/OTP 28: https://www.erlang.org/eeps/eep-0069
Previously the dialyzer considered two types to be the same only if they were structurally equal. For example {number(), number()} created in one place is equivalent to any other {number(), number()} with structural typing. With nominal typing two types are considered the same only if their type has the same name. In Erlang this means that you have functions with specs that say they return a type defined with -nominal Type :: Definition..
Nominal types have slightly worse ergonomics since you need to have APIs for producing and modifying the type. For example even though nom_index is a non_neg_integer(), we can't say Index + 1 in nom.erl. Instead we would need a function nom_index:next/1 which returns a nom_index:t().
Nominal typing is very powerful, however, and a really great addition to the Erlang type system, because the dialyzer can now distinguish between two types which are structurally equivalent bu