vrod

vrod

Struct vs. @type t

I’m pretty new to Elixir. One thing I don’t think I understand is the typespecs, specifically when they deal with structs. A common pattern I’ve seen is that the struct definition is frequently accompanied by a @type t definition, something like this:

defmodule MyStruct do
  
  defstruct x: "",
            y: false,
            z: 0
            
  @type t :: %__MODULE__{
               x: String.t(),
               y: boolean,
               z: integer
             }
end

A struct is defined AND a @type t. If I want to use this struct in function @spec, I have seen both the struct or this type t referenced, e.g.

@spec my_func(%MyStruct{}) :: any

or

@spec my_func(MyStruct.t()) :: any

apply to a function, e.g.

def my_func(%MyStruct{} = input) do
    # something...
end

So my questions are:

  1. Is the @type t special? Or is that just a convention?
  2. Is there any difference between using %MyStruct{} or MyStruct.t() in function specs?
  3. Is there any case where you would use one and not the other?
  4. Is the @type t more “specific” because it can declare the types of various keys in the struct? (Whereas the struct itself only defines the names of the keys, not their data types)

Thanks for any clarifications. I’m sure I missed something in my studies thus far.

Marked As Solved

hauleth

hauleth

Convention.

Yes. If you will use just %MyStruct{} then the types specified in t() will not be used. So:

@type t :: %MyStruct{a: integer()}

@spec pass(%MyStruct{}) :: term()
def pass(t), do: t

@spec fail(t()) :: term()
def fail(t), do: t

s = %MyStruct{a: "bar"}

pass(s)
fail(s) # this will cause Dialyzer error

If there is defined t() then you should always use that.

Yes, as shown above.

17
Post #3

Also Liked

bartblast

bartblast

Creator of Hologram

Another issue worth mentioning is that using %MyModule{} in typespec will create a compile-time dependency, so every time MyModule is changed, the modules that use %MyModule{} in typespecs will need to be recompiled.

harmon25

harmon25

To answer your question, t() is not special, it is just convention.
One thing to remember is that a struct is just a fancy map.

You can create a type with a map that specifies keys and their types just the same:

  @type special_map :: %{some_key: String.t()}

Last Post!

bartblast

bartblast

Creator of Hologram

Another issue worth mentioning is that using %MyModule{} in typespec will create a compile-time dependency, so every time MyModule is changed, the modules that use %MyModule{} in typespecs will need to be recompiled.

Where Next?

Popular in Questions Top

hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
siddhant3030
Hi, I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New

Other popular topics Top

JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54921 245
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New

We're in Beta

About us Mission Statement