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()}

Where Next?

Popular in Questions Top

vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
lessless
I believe there are people here who are dealing with CSV files import on the daily basis, and since Excel is a really popular tool there ...
New
pgiesin
This should be a simple problem but I just can’t seem to figure it out. I have a standalone Elixir app that won’t find the database. Dep...
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
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
Phillipp
Hey, I have a NanoPi-M3 and try to install Elixir on their Ubuntu image. I followed the Raspberry Pi installation instructions from the ...
New
alice
Hey, Just curious what are the main benefits of Elixir compared to Clojure? When is Elixir more useful than Clojure and vice versa? Th...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
Exadra37
Sometimes I want to check if the input into a function is not a blank string. My first approach: defmodule Example do def do_stuff(s...
New
Fl4m3Ph03n1x
About me? ( if you have nothing better to do than reading about some random guy in the internet :stuck_out_tongue: ) Hello all, this is ...
New

Other popular topics Top

peerreynders
Manning 2016 Halloween weekend sale via Deal of the Day Friday, October 28 - Half off all MEAPs - code WM102816LT Saturday, October 29 ...
326 29600 154
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
sergio
I couldn’t find any guides that worked well with Phoenix 1.6.0 and esbuild. I hope this helps people test the waters and eases you into t...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
vac
Hi, I'm quite new in Elixir and I'm trying to format a string to a PEM format. I have the certificate value like MIIDBTCCAe2...... and ...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
electic
Hi, I am new to Elixir. I am trying to use the DateTime component to insert a date into MySQL however the there seems to be no way to fo...
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
New

We're in Beta

About us Mission Statement