# Struct vs. @type t

**URL:** <https://forum.elixirforum.com/t/struct-vs-type-t/32124>\
**Category:** Questions\
**Tags:** structs, typespecs\
**Created:** [June 5, 2020, 5:01pm UTC](https://forum.elixirforum.com/t/struct-vs-type-t/32124 "2020-06-05T17:01:24Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![vrod](https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/v/ee7513/32.png) [@vrod](https://forum.elixirforum.com/u/vrod)\
**Post date:** [June 5, 2020, 5:01pm UTC](https://forum.elixirforum.com/t/struct-vs-type-t/32124/1 "2020-06-05T17:01:24Z")

</div>

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:

```elixir
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.

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

```

or

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

```

apply to a function, e.g.

```elixir
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.

---

<div class="post-metadata">

**Author:** ![harmon25](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/harmon25/32/1274_2.png) [@harmon25](https://forum.elixirforum.com/u/harmon25)\
**Post date:** [June 5, 2020, 5:08pm UTC](https://forum.elixirforum.com/t/struct-vs-type-t/32124/2 "2020-06-05T17:08:57Z")

</div>

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:

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

```

---

<div class="post-metadata">

**Author:** ![hauleth](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/hauleth/32/18942_2.png) [@hauleth](https://forum.elixirforum.com/u/hauleth)\
**Post date:** [June 5, 2020, 5:34pm UTC](https://forum.elixirforum.com/t/struct-vs-type-t/32124/3 "2020-06-05T17:34:58Z")

</div>

> [@vrod](#):
>
> Is the `@type t` special? Or is that just a convention?

Convention.

> [@vrod](#):
>
> Is there any difference between using `%MyStruct{}` or `MyStruct.t()` in function specs?

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

```elixir
@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

```

> [@vrod](#):
>
> Is there any case where you would use one and not the other?

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

> [@vrod](#):
>
> 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)

Yes, as shown above.

---

<div class="post-metadata">

**Author:** ![vrod](https://forum.elixirforum.com/letter_avatar_proxy/v4/letter/v/ee7513/32.png) [@vrod](https://forum.elixirforum.com/u/vrod)\
**Post date:** [June 5, 2020, 5:58pm UTC](https://forum.elixirforum.com/t/struct-vs-type-t/32124/4 "2020-06-05T17:58:58Z")

</div>

Thanks! That makes sense.

---

<div class="post-metadata">

**Author:** ![bartblast](https://forum.elixirforum.com/user_avatar/forum.elixirforum.com/bartblast/32/17647_2.png) [@bartblast](https://forum.elixirforum.com/u/bartblast)\
**Post date:** [April 26, 2023, 4:18pm UTC](https://forum.elixirforum.com/t/struct-vs-type-t/32124/5 "2023-04-26T16:18:28Z")

</div>

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.
