Elixir v1.0.5 Kernel.Typespec

Provides macros and functions for working with typespecs.

Elixir comes with a notation for declaring types and specifications. Elixir is dynamically typed, as such typespecs are never used by the compiler to optimize or modify code. Still, using typespecs is useful as documentation and tools such as Dialyzer can analyze the code with typespecs to find bugs.

The attributes @type, @opaque, @typep, @spec and @callback available in modules are handled by the equivalent macros defined by this module. See sub-sections “Defining a type” and “Defining a specification” below.

Types and their syntax

The type syntax provided by Elixir is fairly similar to the one in Erlang.

Most of the built-in types provided in Erlang (for example, pid()) are expressed the same way: pid() or simply pid. Parametrized types are also supported (list(integer)) and so are remote types (Enum.t).

Integers and atom literals are allowed as types (ex. 1, :atom or false). All other types are built of unions of predefined types. Certain shorthands are allowed, such as [...], <<>> and {...}.

Predefined types

Type :: any         # the top type, the set of all terms
      | none        # the bottom type, contains no terms
      | pid
      | port
      | reference
      | Atom
      | Bitstring
      | float
      | Fun
      | Integer
      | List
      | Map
      | Tuple
      | Union
      | UserDefined # Described in section "Defining a type"

Atom :: atom
      | ElixirAtom # `:foo`, `:bar`, ...

Bitstring :: <<>>
           | << _ :: M >>             # M is a positive integer
           | << _ :: _ * N >>         # N is a positive integer
           | << _ :: M, _ :: _ * N >>

Fun :: (... -> any)    # any function
     | (... -> Type)   # any arity, returning Type
     | (() -> Type))
     | (TList -> Type)

Integer :: integer
         | ElixirInteger                # ..., -1, 0, 1, ... 42 ...
         | ElixirInteger..ElixirInteger # an integer range

List :: list(Type)                        # proper list ([]-terminated)
      | improper_list(Type1, Type2)       # Type1=contents, Type2=termination
      | maybe_improper_list(Type1, Type2) # Type1 and Type2 as above
      | nonempty_list(Type)               # proper non-empty list
      | []                                # empty list
      | [Type]                            # shorthand for list(Type)
      | [...]                             # shorthand for nonempty_list()
      | [Type, ...]                       # shorthand for nonempty_list(Type)
      | [Keyword]

Map :: map()            # map of any size
     | %{}              # map of any size
     | %Struct{}        # struct (see defstruct/1)
     | %Struct{Keyword}
     | %{Keyword}
     | %{Pairs}

Tuple :: tuple                 # a tuple of any size
       | {}                    # empty tuple
       | {TList}
       | record(Atom)          # record (see Record)
       | record(Atom, Keyword)

Keyword :: ElixirAtom: Type
         | ElixirAtom: Type, Keyword

Pairs :: Type => Type
       | Type => Type, Pairs

TList :: Type
       | Type, TList

Union :: Type | Type

Bit strings

Bit string with a base size of 3:

<< _ :: 3 >>

Bit string with a unit size of 8:

<< _ :: _ * 8 >>

Anonymous functions

Any anonymous function:

((...) -> any)
(... -> any)

Anonymous function with arity of zero:

(() -> type)

Anonymous function with some arity:

((type, type) -> type)
(type, type -> type)

Built-in types

Built-in typeDefined as
termany
binary<< _ :: _ * 8 >>
bitstring<< _ :: _ * 1 >>
booleanfalse | true
byte0..255
char0..0x10ffff
numberinteger | float
char_list[char]
list[any]
maybe_improper_listmaybe_improper_list(any, any)
nonempty_listnonempty_list(any)
iodataiolist | binary
iolistmaybe_improper_list(byte | binary | iolist, binary | [])
moduleatom | tuple
mfa{atom, atom, arity}
arity0..255
nodeatom
timeout:infinity | non_neg_integer
no_returnnone
fun(... -> any)

Some built-in types cannot be expressed with valid syntax according to the language defined above.

Built-in typeCan be interpreted as
non_neg_integer0..
pos_integer1..
neg_integer..-1

Types defined in other modules are referred to as “remote types”, they are referenced as Module.type_name (ex. Enum.t or String.t).

Defining a type

@type type_name :: type
@typep type_name :: type
@opaque type_name :: type

A type defined with @typep is private. An opaque type, defined with @opaque is a type where the internal structure of the type will not be visible, but the type is still public.

Types can be parametrised by defining variables as parameters, these variables can then be used to define the type.

@type dict(key, value) :: [{key, value}]

Defining a specification

@spec function_name(type1, type2) :: return_type
@callback function_name(type1, type2) :: return_type

Callbacks are used to define the callbacks functions of behaviours (see Behaviour).

Guards can be used to restrict type variables given as arguments to the function.

@spec function(arg) :: [arg] when arg: atom

Type variables with no restriction can also be defined.

@spec function(arg) :: [arg] when arg: var

Specifications can be overloaded just like ordinary functions.

@spec function(integer) :: atom
@spec function(atom)    :: integer

Notes

Elixir discourages the use of type string as it might be confused with binaries which are referred to as “strings” in Elixir (as opposed to character lists). In order to use the type that is called string in Erlang, one has to use the char_list type which is a synonym for string. If you use string, you’ll get a warning from the compiler.

If you want to refer to the “string” type (the one operated on by functions in the String module), use String.t type instead.

Summary

Functions

Returns all callbacks available from the module’s beam code

Returns all specs available from the module’s beam code

Returns all type docs available from the module’s beam code

Returns all types available from the module’s beam code

Defines a spec by receiving a typespec expression

Defines a type, typep or opaque by receiving a typespec expression

Returns true if the current module defines a callback. This function is only available for modules being compiled

Returns true if the current module defines a given spec. This function is only available for modules being compiled

Returns true if the current module defines a given type (private, opaque or not). This function is only available for modules being compiled

Converts a spec clause back to Elixir AST

Converts a type clause back to Elixir AST

Macros

Defines a callback. This macro is responsible for handling the attribute @callback

Defines an opaque type. This macro is responsible for handling the attribute @opaque

Defines a spec. This macro is responsible for handling the attribute @spec

Defines a type. This macro is responsible for handling the attribute @type

Defines a private type. This macro is responsible for handling the attribute @typep

Functions

beam_callbacks(module)

Specs

beam_callbacks(module | binary) :: [tuple] | nil

Returns all callbacks available from the module’s beam code.

The result is returned as a list of tuples where the first element is spec name and arity and the second is the spec.

The module must have a corresponding beam file which can be located by the runtime system.

beam_specs(module)

Specs

beam_specs(module | binary) :: [tuple] | nil

Returns all specs available from the module’s beam code.

The result is returned as a list of tuples where the first element is spec name and arity and the second is the spec.

The module must have a corresponding beam file which can be located by the runtime system.

beam_typedocs(module)

Specs

beam_typedocs(module | binary) :: [tuple] | nil

Returns all type docs available from the module’s beam code.

The result is returned as a list of tuples where the first element is the pair of type name and arity and the second element is the documentation.

The module must have a corresponding beam file which can be located by the runtime system.

beam_types(module)

Specs

beam_types(module | binary) :: [tuple] | nil

Returns all types available from the module’s beam code.

The result is returned as a list of tuples where the first element is the type (:typep, :type and :opaque).

The module must have a corresponding beam file which can be located by the runtime system.

define_spec(kind, expr, env)

Defines a spec by receiving a typespec expression.

define_type(kind, expr, doc \\ nil, env)

Defines a type, typep or opaque by receiving a typespec expression.

defines_callback?(module, name, arity)

Returns true if the current module defines a callback. This function is only available for modules being compiled.

defines_spec?(module, name, arity)

Returns true if the current module defines a given spec. This function is only available for modules being compiled.

defines_type?(module, name, arity)

Returns true if the current module defines a given type (private, opaque or not). This function is only available for modules being compiled.

spec_to_ast(name, arg2)

Converts a spec clause back to Elixir AST.

type_to_ast(arg1)

Converts a type clause back to Elixir AST.

Macros

defcallback(spec)

Defines a callback. This macro is responsible for handling the attribute @callback.

Examples

@callback add(number, number) :: number
defopaque(type)

Defines an opaque type. This macro is responsible for handling the attribute @opaque.

Examples

@opaque my_type :: atom
defspec(spec)

Defines a spec. This macro is responsible for handling the attribute @spec.

Examples

@spec add(number, number) :: number
deftype(type)

Defines a type. This macro is responsible for handling the attribute @type.

Examples

@type my_type :: atom
deftypep(type)

Defines a private type. This macro is responsible for handling the attribute @typep.

Examples

@typep my_type :: atom