Installation
Add :typed_structor to your dependencies in mix.exs:
def deps do
[
{:typed_structor, "~> 0.6"}
]
endFormatter Setup
Add :typed_structor to your .formatter.exs for proper indentation:
[
import_deps: [..., :typed_structor],
inputs: [...]
]Getting Started
Use typed_structor blocks to define fields with their types:
defmodule User do
use TypedStructor
typed_structor do
field :id, pos_integer(), enforce: true # Required, never nil
field :name, String.t() # Optional, nullable
field :role, String.t(), default: "user" # Has default, not nullable
end
endNullability Rules
The interaction between :enforce, :default, and :null determines whether a field's type includes nil:
:default | :enforce | :null | Type includes nil? |
|---|---|---|---|
unset | false | true | yes |
unset | false | false | no |
set | - | - | no |
| - | true | - | no |
You can set :null at the block level to change the default for all fields:
typed_structor null: false do
field :id, integer() # Not nullable
field :email, String.t() # Not nullable
field :phone, String.t(), null: true # Override: nullable
endOptions
Opaque Types
Use type_kind: :opaque to hide implementation details:
typed_structor type_kind: :opaque do
field :secret, String.t()
end
# Generates: @opaque t() :: %__MODULE__{...}Custom Type Names
Override the default t() type name:
typed_structor type_name: :user_data do
field :id, pos_integer()
end
# Generates: @type user_data() :: %__MODULE__{...}Type Parameters
Create generic types with parameter/1:
typed_structor do
parameter :value_type
parameter :error_type
field :value, value_type
field :error, error_type
end
# Generates: @type t(value_type, error_type) :: %__MODULE__{...}Nested Modules
Define structs in submodules:
defmodule User do
use TypedStructor
typed_structor module: Profile do
field :email, String.t(), enforce: true
field :bio, String.t()
end
end
# Creates User.Profile with its own struct and typePlugins
Extend TypedStructor's behavior with plugins that run at compile time:
typed_structor do
plugin Guides.Plugins.Accessible
field :id, pos_integer()
field :name, String.t()
endSee the Plugin Guides for examples and instructions on writing your own.
Documentation
Add @typedoc inside the block, and @moduledoc at the module level as usual:
defmodule User do
@moduledoc "User account data"
use TypedStructor
typed_structor do
@typedoc "A user with authentication details"
field :id, pos_integer()
field :name, String.t()
end
end
Summary
Functions
Defines a field in a typed_structor/2.
You can override the options set by typed_structor/2 by passing options.
Defines a type parameter in a typed_structor/2.
Registers a plugin for the currently defined struct.
Defines a struct with type information.
Functions
Defines a field in a typed_structor/2.
You can override the options set by typed_structor/2 by passing options.
Example
# A field named :example of type String.t()
field :example, String.t()Options
:default- sets the default value for the field:enforce- if set totrue, enforces the field, and makes its type non-nullable if:defaultis not set:null- when set totrue(the default), allowsnilto be added to the field type when:defaultis not set and:enforceis not set; when set tofalse, preventsnilfrom being added in that case
How :default, :enforce and :null affect type and @enforce_keys
:default:enforce:nulltype@enforce_keysset- - t()excludedunsettrue- t()includedunsetfalsetruet() | nilexcludedunsetfalsefalset()excluded
Defines a type parameter in a typed_structor/2.
Example
# A type parameter named int
parameter :int
field :number, int # not int()
Registers a plugin for the currently defined struct.
Example
typed_structor do
plugin MyPlugin
field :string, String.t()
endFor more information on how to define your own plugins, please see
TypedStructor.Plugin. To use a third-party plugin, please refer directly to
its documentation.
Defines a struct with type information.
Inside a typed_structor block, you can define fields with the field/3 macro.
Options
:module- if provided, a new submodule will be created with the struct.:enforce- iftrue, the struct will enforce the keys, seefield/3options for more information.:null- iftrue(default), fields without a default value and not enforced will haveniladded to their type. Iffalse, preventsnilfrom being added.:definer- the definer module to use to define the struct, record or exception. Defaults to:defstruct. It also accepts a macro that receives the definition struct and returns the AST. See definer section below.:type_kind- the kind of type to use for the struct. Defaults totype, can beopaqueortypep.:type_name- the name of the type to use for the struct. Defaults tot.
Definer
The available definers are:
:defstruct, which defines a struct and a type for a given definition:defexception, which defines an exception and a type for a given definition:defrecord, which defines record macros and a type for a given definition:defrecordp, which defines private record macros and a type for a given definition
:defstruct options
:define_struct- iffalse, the type will be defined, but the struct will not be defined. Defaults totrue.
:defexception options
:define_struct- iffalse, the type will be defined, but the struct will not be defined. Defaults totrue.
:defrecord and :defrecordp options
:record_name(required) - the name of the record, it must be provided.:record_tag- if set, the record will be tagged with the given value. Defaults tonil.:define_record- iffalse, the type will be defined, but the record will not be defined. Defaults totrue.
custom definer
defmodule MyStruct do
use TypedStructor
typed_structor definer: MyDefiner do
field :name, String.t()
field :age, integer()
end
endExamples
defmodule MyStruct do
use TypedStructor
typed_structor do
field :name, String.t()
field :age, integer()
end
endCreates the struct in a submodule instead:
defmodule MyStruct do
use TypedStructor
typed_structor module: Struct do
field :name, String.t()
field :age, integer()
end
endTo add a @typedoc to the struct type and @moduledoc to the submodule,
just add the module attribute in the typed_structor block:
defmodule MyStruct do
use TypedStructor
typed_structor module: Struct do
@typedoc "A typed struct"
@moduledoc "A submodule"
field :name, String.t()
field :age, integer()
end
end