23
votes

In std Elixir packages there are a lot of lines like

@type t :: %__MODULE__{}

I know that the @type annotation is used to alias short notation of type in @spec annotations, but this line is used in modules such as uri.ex which has no @spec annotations at all.

What is the purpose of this annotation?

1

1 Answers

35
votes

First of all, types specified with the @type directive are public by default (as opposed to types defined with @typep). This means that even if a module has no specs in it, defining a type allows other developers to use that type when writing their functions:

@doc "Computes the length of a URI."
@spec foo(URI.t) :: non_neg_integer
def foo(uri), do: # ...

__MODULE__ is a special form that expands to the current module name as an atom (see the docs for it), so this:

defmodule MyModule do
  @type t :: %__MODULE__{}
end

will define a MyModule.t type. The most common use of the t type is for representing structs and protocols (e.g., Enum.t). This pattern is extremely common:

defmodule User do
  defstruct [:name, :email]
  @type t :: %__MODULE__{name: String.t, email: String.t}
end