ProductPromotion
Logo

Elixir

made by https://0x3d.site

GitHub - elixir-typed-structor/typed_structor: TypedStructor is a library for defining structs with types effortlessly.
TypedStructor is a library for defining structs with types effortlessly. - elixir-typed-structor/typed_structor
Visit Site

GitHub - elixir-typed-structor/typed_structor: TypedStructor is a library for defining structs with types effortlessly.

GitHub - elixir-typed-structor/typed_structor: TypedStructor is a library for defining structs with types effortlessly.

TypedStructor

Build Status Hex.pm Document Plugin guides

TypedStructor is a library for defining structs with types effortlessly. (This library is a rewritten version of TypedStruct because it is no longer actively maintained.)

Installation

Add :typed_structor to the list of dependencies in mix.exs:

def deps do
  [
    {:typed_structor, "~> 0.5"}
  ]
end

Add :typed_structor to your .formatter.exs file

[
  # import the formatter rules from `:typed_structor`
  import_deps: [..., :typed_structor],
  inputs: [...]
]

Usage

General usage

To define a struct with types, use TypedStructor, and then define fields under the TypedStructor.typed_structor/2 macro, using the TypedStructor.field/3 macro to define each field.

defmodule User do
  # use TypedStructor to import the `typed_structor` macro
  use TypedStructor

  typed_structor do
    # Define each field with the `field` macro.
    field :id, pos_integer()

    # set a default value
    field :name, String.t(), default: "Unknown"

    # enforce a field
    field :age, non_neg_integer(), enforce: true
  end
end

This is equivalent to:

defmodule User do
  defstruct [:id, :name, :age]

  @type t() :: %__MODULE__{
    id: pos_integer() | nil,
    # Note: The 'name' can not be nil, for it has a default value.
    name: String.t(),
    age: non_neg_integer()
  }
end

Check TypedStructor.typed_structor/2 and TypedStructor.field/3 for more information.

Options

You can also generate an opaque type for the struct, even changing the type name:

defmodule User do
  use TypedStructor

  typed_structor type_kind: :opaque, type_name: :profile do
    field :id, pos_integer()
    field :name, String.t()
    field :age, non_neg_integer()
  end
end

This is equivalent to:

defmodule User do
  use TypedStructor

  defstruct [:id, :name, :age]

  @opaque profile() :: %__MODULE__{
    id: pos_integer() | nil,
    name: String.t() | nil,
    age: non_neg_integer() | nil
  }
end

Type parameters also can be defined:

defmodule User do
  use TypedStructor

  typed_structor do
    parameter :id
    parameter :name

    field :id, id
    field :name, name
    field :age, non_neg_integer()
  end
end

becomes:

defmodule User do
  @type t(id, name) :: %__MODULE__{
    id: id | nil,
    name: name | nil,
    age: non_neg_integer() | nil
  }

  defstruct [:id, :name, :age]
end

If you prefer to define a struct in a submodule, you can use the module option with TypedStructor. This allows you to encapsulate the struct definition within a specific submodule context.

Consider this example:

defmodule User do
  use TypedStructor

  # `%User.Profile{}` is generated
  typed_structor module: Profile do
    field :id, pos_integer()
    field :name, String.t()
    field :age, non_neg_integer()
  end
end

When defining a struct in a submodule, the typed_structor block functions similarly to a defmodule block. Therefore, the previous example can be alternatively written as:

defmodule User do
  defmodule Profile do
    use TypedStructor

    typed_structor do
      field :id, pos_integer()
      field :name, String.t()
      field :age, non_neg_integer()
    end
  end
end

Furthermore, the typed_structor block allows you to define functions, derive protocols, and more, just as you would within a defmodule block. Here's a example:

defmodule User do
  use TypedStructor

  typed_structor module: Profile, define_struct: false do
    @derive {Jason.Encoder, only: [:email]}
    field :email, String.t()

    use Ecto.Schema
    @primary_key false

    schema "users" do
      Ecto.Schema.field(:email, :string)
    end

    import Ecto.Changeset

    def changeset(%__MODULE__{} = user, attrs) do
      user
      |> cast(attrs, [:email])
      |> validate_required([:email])
    end
  end
end

Now, you can interact with these structures:

iex> User.Profile.__struct__()
%User.Profile{__meta__: #Ecto.Schema.Metadata<:built, "users">, email: nil}
iex> Jason.encode!(%User.Profile{})
"{\"email\":null}"
iex> User.Profile.changeset(%User.Profile{}, %{"email" => "[email protected]"})
#Ecto.Changeset<
  action: nil,
  changes: %{email: "[email protected]"},
  errors: [],
  data: #User.Profile<>,
  valid?: true
>

Define an Exception

In Elixir, an exception is defined as a struct that includes a special field named __exception__. To define an exception, use the defexception definer within the typed_structor block.

defmodule HTTPException do
  use TypedStructor

  typed_structor definer: :defexception, enforce: true do
    field :status, non_neg_integer()
  end

  @impl Exception
  def message(%__MODULE__{status: status}) do
    "HTTP status #{status}"
  end
end

Define records related macros

In Elixir, you can use the Record module to define and work with Erlang records, making interoperability between Elixir and Erlang more seamless.

defmodule TypedStructor.User do
  use TypedStructor

  typed_structor definer: :defrecord, record_name: :user, record_tag: User, enforce: true do
    field :name, String.t()
    field :age, pos_integer()
  end
end

Documentation

To add a @typedoc to the struct type, just add the attribute in the typed_structor block:

typed_structor do
  @typedoc "A typed user"

  field :id, pos_integer()
  field :name, String.t()
  field :age, non_neg_integer()
end

You can also document submodules this way:

typedstructor module: Profile do
  @moduledoc "A user profile struct"
  @typedoc "A typed user profile"

  field :id, pos_integer()
  field :name, String.t()
  field :age, non_neg_integer()
end

Plugins

TypedStructor offers a plugin system to enhance functionality. For details on creating a plugin, refer to the TypedStructor.Plugin module.

Here is a example of Guides.Plugins.Accessible plugin to define Access behavior for the struct.

defmodule User do
  use TypedStructor

  typed_structor do
    plugin Guides.Plugins.Accessible

    field :id, pos_integer()
    field :name, String.t()
    field :age, non_neg_integer()
  end
end

user = %User{id: 1, name: "Phil", age: 20}
get_in(user, [:name]) # => "Phil"

Plugins guides {: .tip}

Here are some Plugin Guides for creating your own plugins. Please check them out and feel free to copy-paste the code.

Articles
to learn more about the elixir concepts.

Resources
which are currently available to browse on.

mail [email protected] to add your project or resources here 🔥.

FAQ's
to know more about the topic.

mail [email protected] to add your project or resources here 🔥.

Queries
or most google FAQ's about Elixir.

mail [email protected] to add more queries here 🔍.

More Sites
to check out once you're finished browsing here.

0x3d
https://www.0x3d.site/
0x3d is designed for aggregating information.
NodeJS
https://nodejs.0x3d.site/
NodeJS Online Directory
Cross Platform
https://cross-platform.0x3d.site/
Cross Platform Online Directory
Open Source
https://open-source.0x3d.site/
Open Source Online Directory
Analytics
https://analytics.0x3d.site/
Analytics Online Directory
JavaScript
https://javascript.0x3d.site/
JavaScript Online Directory
GoLang
https://golang.0x3d.site/
GoLang Online Directory
Python
https://python.0x3d.site/
Python Online Directory
Swift
https://swift.0x3d.site/
Swift Online Directory
Rust
https://rust.0x3d.site/
Rust Online Directory
Scala
https://scala.0x3d.site/
Scala Online Directory
Ruby
https://ruby.0x3d.site/
Ruby Online Directory
Clojure
https://clojure.0x3d.site/
Clojure Online Directory
Elixir
https://elixir.0x3d.site/
Elixir Online Directory
Elm
https://elm.0x3d.site/
Elm Online Directory
Lua
https://lua.0x3d.site/
Lua Online Directory
C Programming
https://c-programming.0x3d.site/
C Programming Online Directory
C++ Programming
https://cpp-programming.0x3d.site/
C++ Programming Online Directory
R Programming
https://r-programming.0x3d.site/
R Programming Online Directory
Perl
https://perl.0x3d.site/
Perl Online Directory
Java
https://java.0x3d.site/
Java Online Directory
Kotlin
https://kotlin.0x3d.site/
Kotlin Online Directory
PHP
https://php.0x3d.site/
PHP Online Directory
React JS
https://react.0x3d.site/
React JS Online Directory
Angular
https://angular.0x3d.site/
Angular JS Online Directory