Types can be read from the module’s bytecode like the following at compile-time:
defmodule MyModule do
@type one_type :: atom()
@opaque another_type :: integer()
@after_compile {MyModule, :_collect_types}
def _collect_types(_env, bytecode) do
{:ok, types} = Code.Typespec.fetch_types(bytecode)
Enum.map(types, fn {kind, type} ->
type_ast = Code.Typespec.type_to_quoted(type)
type_ast
|> Macro.to_string()
|> IO.inspect(label: kind)
end)
end
end
it prints:
opaque: "another_type() :: integer()"
type: "one_type() :: atom()"