Fl4m3Ph03n1x

Fl4m3Ph03n1x

Gradient does not recognize type of TypedStruct structures

Background

I have a module that uses TypedStruct to create structs. This is the code:

defmodule Shared.Data.Authorization do
  @moduledoc """
  Saves authorization details for a user. It also contains other details.
  """

  use TypedStruct

  alias Shared.Utils.Structs

  @type authorization :: %{
          (cookie :: String.t()) => String.t(),
          (token :: String.t()) => String.t()
        }

  @derive Jason.Encoder
  typedstruct enforce: true do
    @typedoc "Authorization information for a user"

    field(:cookie, String.t())
    field(:token, String.t())
  end

  @spec new(authorization()) :: __MODULE__.t()
  def new(%{"cookie" => cookie, "token" => token} = auth)
      when is_binary(cookie) and is_binary(token) do
    Structs.string_map_to_struct(auth, __MODULE__)
  end
end

The problem here is that Gradient does not seem to understand that t() is created, so it errors out:

 lib/data/authorization.ex: The function call on line 26 is expected to have type t() but it has type struct()
 24   def new(%{"cookie" => cookie, "token" => token} = auth)
 25       when is_binary(cookie) and is_binary(token) do
 26     Structs.string_map_to_struct(auth, __MODULE__)
 27   end

For additional context, here is the string_map_to_struct code:

  @spec string_map_to_struct(map, module | struct) :: struct
  def string_map_to_struct(data, target_struct) do
    data
    |> Morphix.atomorphiform!() # string_map to atom_map
    |> data_to_struct(target_struct)
  end

  @spec data_to_struct(Enumerable.t(), module | struct) :: struct
  def data_to_struct(data, target_struct), do: struct(target_struct, data)

Temporary fix

I decided to convert that code into its native form using defstruct:

defmodule Shared.Data.Authorization do
  @moduledoc """
  Saves authorization details for a user. It also contains other details.
  """

  alias Shared.Utils.Structs

  @enforce_keys [:cookie, :token]
  defstruct [:cookie, :token]

  @type authorization :: %{
          (cookie :: String.t()) => String.t(),
          (token :: String.t()) => String.t()
        }

  @typedoc "Authorization information for a user"
  @type t() :: %__MODULE__{
          cookie: String.t(),
          token: String.t()
        }

  @spec new(authorization()) :: t()
  def new(%{"cookie" => cookie, "token" => token} = auth)
      when is_binary(cookie) and is_binary(token) do
    Structs.string_map_to_struct(auth, __MODULE__)
  end
end

Gradient does not complain here.

Question

Is there a fix for this?
(other than removing typed struct?)

Most Liked

mafinar

mafinar

It’s cool that you also raised issue here: Gradient does not recognize type of TypedStruct structures · Issue #165 · esl/gradient · GitHub I am adding this as comment so that anyone coming to this post can go and follow the progress there. I myself am interested in this one. Thanks.

Fl4m3Ph03n1x

Fl4m3Ph03n1x

I usually update both threads if/when the issue is solved, so I got you covered there :stuck_out_tongue:

Where Next?

Popular Backend topics Top

Kurisu
Following on an old discussion I started on Elixir Forum here, I finally made my mind to learn Ruby on Rails in addition to Elixir/Phoen...
New
dimitarvp
Hey everyone, I resumed work on my Elixir <=> SQLite library (which uses a Rust NIF underneath) and I am in a need of small and we...
New
ohm
Does anybody have good learning resources with regards to going into Event Driven Design, Architecture or Sourcing? I got recommended Er...
New
mrmurphy
I’ve run into a situation where I’ve got a list of posts inside of a container that uses phx-update=“prepend”, and the posts on the socke...
New
sampu
I have a use case where a client is invoking a Rest endpoint via a load balancer, which in turn invokes a third party endpoint which is r...
New
JimmyCarterSon
I am following this tutorial . I have followed carefully correcting errors as I go. The app allows you to create a blog post and add comm...
New
MarkIden
Hi, Recommend pls your favorite learning resources in Go, with best books, podcasts etc.
/go
New
Fl4m3Ph03n1x
Background I have a release file inside a tarball. However I want the final release to have some additional files and to move things aro...
New
AstonJ
If you’re getting errors like this: psql: error: connection to server on socket “/tmp/.s.PGSQL.5432” failed: No such file or directory ...
New
theodor
I have this app where there are a bunch of users that cannot access their account anymore after they updated their Android device to Andr...
New

Other popular topics Top

PragmaticBookshelf
Write Elixir tests that you can be proud of. Dive into Elixir’s test philosophy and gain mastery over the terminology and concepts that u...
New
AstonJ
What chair do you have while working… and why? Is there a ‘best’ type of chair or working position for developers?
New
PragmaticBookshelf
From finance to artificial intelligence, genetic algorithms are a powerful tool with a wide array of applications. But you don't need an ...
New
AstonJ
I ended up cancelling my Moonlander order as I think it’s just going to be a bit too bulky for me. I think the Planck and the Preonic (o...
New
AstonJ
In case anyone else is wondering why Ruby 3 doesn’t show when you do asdf list-all ruby :man_facepalming: do this first: asdf plugin-upd...
New
PragmaticBookshelf
Learn different ways of writing concurrent code in Elixir and increase your application's performance, without sacrificing scalability or...
New
New
PragmaticBookshelf
Author Spotlight Mike Riley @mriley This month, we turn the spotlight on Mike Riley, author of Portable Python Projects. Mike’s book ...
New
PragmaticBookshelf
Author Spotlight: VM Brasseur @vmbrasseur We have a treat for you today! We turn the spotlight onto Open Source as we sit down with V...
New
PragmaticBookshelf
Explore the power of Ash Framework by modeling and building the domain for a real-world web application. Rebecca Le @sevenseacat and ...
New