Correct way to get type from schema

i have a schema

defmodule Hello.Database.Template do
  schema "templates" do
    field(:name, :string)
    field(:description, :string)
  end
end

and when I call it in another module e.g.

defmodule Hello.Worker.SomethingElse do
  alias Hello.Database.Template

  @spec something(map()) :: Template.t()
  def something(map) do
  end
end

Dialyzer will complain that there is no Template.t() . Where would be the best place to define this type? would this go inside of Hello.Database.Template and look something like this?

defmodule Hello.Database.Template do
  @type %__MODULE__{
  name: string,
  description: string
  }
  
  schema "templates" do
    field(:name, :string)
    field(:description, :string)
  end
end
1 Like

Pretty much. See the typespecs reference.

The proper syntax would be:

@type t :: %__MODULE__{
  name: String.t,
  description: String.t,
}

Note that t is just the name of the type. It could be anything, but t is the convention for “the default type of this module”, essentially.

2 Likes

Oops. I did make some errors. Thanks.

It just felt a little weird to me to put the schema and the type at the same place but I could not figure out where it would live a bit better. I’ll add it into the schema file. Thank you!

I think this may eventually be handled automatically with struct type inference. Does anyone know for sure?

Usage example:

def something(%Template{} = some_var) do
end

I’ve used TypedEctoSchema for years and it works great

2 Likes

hey @jam

If you were to write a spec for that how would that look?

@spec something(map()) :: any()
def something(%Template{} = some_var) do
end

or

@spec something(Template.t()) :: any()
def something(%Template{} = some_var) do
end

We can always pattern match to make sure we are getting the type

I’m hoping that it won’t be necessary in the long term. :slightly_smiling_face: For things where I can’t rely on the compiler, I imagine it might look something like the 2nd but I think it depends on what the new type syntax looks like when it’s rolled out.