---
title: "Difference between type and type alias in Elm"
description: "type alias vs type in Elm"
canonical_url: "https://www.bigbinary.com/blog/difference-between-type-and-type-alias-in-elm"
markdown_url: "https://www.bigbinary.com/blog/difference-between-type-and-type-alias-in-elm.md"
---

# Difference between type and type alias in Elm

type alias vs type in Elm

- Author: Neeraj Singh
- Published: July 12, 2017
- Categories: Misc

What is the difference between `type` and `type alias`.

Elm FAQ has
[an answer](http://faq.elm-community.org/#what-is-the-difference-between-type-and-type-alias)
to this question. However I could not fully understand the answer.

This is my attempt in explaining it.

## What is type

In Elm everything has a type. Fire up `elm-repl` and you will see 4 is a
`number` and "hello" is a `String`.

```elm
> 4
4 : number

> "hello"
"hello" : String
```

Let's assume that we are working with users records and we have following
attributes of those users.

- Name
- Age
- Status (Active or Inactive)

It's pretty clear that "Name" should be of type "String" and "Age" should be of
type "number".

Let's think about a moment what is the type of "Status". What is "Active" and
"Inactive" in terms of type.

`Active` and `Inactive` are two valid values of `Status`. In other programming
languages we might represent `Status` as an enum.

In Elm we need to create a new type. And that can be done as shown here.

```elm
type Status = Active | Inactive
```

Second thing we are doing is that we are stating that the valid values for this
new type are `Active` and `Inactive`.

When I discussed this code with my team members they asked me to show where is
`Active` and `Inactive` defined. Good question.

The simple answer is that they are not defined anywhere. They do not need to be
defined. What needs definition is the new type that is being created.

What makes understanding it a bit hard for people coming from Ruby, Java and
such background is that these people (including me) are looking at `Active` and
`Inactive` as a class or a constant which is not the right way to look at.

`Active` and `Inactive` are the valid values for type `Status`.

```elm
> Active
-- NAMING ERROR ----------

Cannot find variable `Active`

3|   Active
     ^^^^^^
```

As you can see repl is not sure what `Active` is.

We can solve this by pasting following code in repl.

```elm
type Status = Active | Inactive
```

Now we can run the same code again. This time no error.

```elm
> Active
Active : Repl.Status
```

## What is type alias

Let's see a simple application which just prints name and age of a single user.

[Here](https://gist.github.com/neerajsingh0101/60627801877312ea95e328f704e5245a)
is the code. I'm posting screenshot of the same below with certain part
highlighted.

![code without type alias](https://www.bigbinary.com/blog/images/images_used_in_blog/2017/difference-between-type-and-type-alias-in-elm/code-without-type-alias.png)

As you can see `{ name : String, age : Int }` is repeated at four different
places. In a bigger application it might get repeated more often.

This is what `type alias` does. It removes repetition. It removes verbosity.

As the name suggests this is just an alias. Note that `type` creates a new type
whereas `type alias` is literally saving keystrokes. `type alias` does not
create a new `type`.

Now if you read the FAQ answer again then hopefully it will make morse sense
now.

[Here](https://gist.github.com/neerajsingh0101/8e7756a1b7588538ac16526ce2bfc772)
is modified code using `type alias`.

## Why use type alias Username : String

While browsing Elm code in general, I came across following code.

```elm
type alias Username = String
```

Question is what does code like this buy us. All it does is that instead of
`String` I can now type `Username`.

First let's see how it might be used.

Let's assume that we have a function which returns `Status` of a user for the
given username.

The function might have implementation as shown below.

```elm
getUserStatus username =
  make_db_call_and_return_user_status
```

Now let's think about what the type annotation (rubyist think of it as method
signature ) of function `getUserStatus` might look like.

It takes `username` as input and returns user record.

So the type annotation might look like

```elm
getUserStatus : String -> Status
```

This works. However the issue is that `String` is not expressive enough. It can
be made more expressive if the signature were

```elm
getUserStatus : Username -> Status
```

Now that we know about `type alias` all we need to do is

```elm
type alias Username = String
```

This makes code more expressive.

## No recursion with type alias

An example of where we might need recursion is while designing commenting
system. A comment can have sub-comments. However since `type alias` is just a
substitution and recursion does not work with it.

```elm
> type alias Comment = { message : String, responses : List Comment }

This type alias is recursive, forming an infinite type!

2| type alias Comment = { message : String, responses : List Comment }
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
When I expand a recursive type alias, it just keeps getting bigger and bigger.
So dealiasing results in an infinitely large type! Try this instead:

    type Comment
        = Comment { message : String, responses : List Comment }

This is kind of a subtle distinction. I suggested the naive fix, but you can
often do something a bit nicer. So I would recommend reading more at:
<https://github.com/elm-lang/elm-compiler/blob/0.18.0/hints/recursive-alias.md>
```

[Hint for Recursive Type Aliases](https://github.com/elm-lang/elm-compiler/blob/master/hints/recursive-alias.md)
discusses this issue in greater detail and it also has solution to the problem
of recursion.

## Dual role of type alias as constructor and type

Let's say that we have following code.

```elm
type alias UserInfo =
    { name : String, age : Int }
```

Now we can use `UserInfo` as a constructor to create records.

```elm
> type alias UserInfo = { name : String, age : Int }
> sam = UserInfo "Sam" 24
{ name = "Sam", age = 24 } : Repl.UserInfo
```

In the above case we used `UserInfo` as a **constructor** to create new user
records. We did not use `UserInfo` as a `type`.

Now let's see another function.

```elm
type alias UserInfo =
    { name : String, age : Int }


getUserAge : UserInfo -> Int
getUserAge userinfo =
    userinfo.age
```

In this case `UserInfo` is being used in **type annotation** as **type** and not
as **constructor**.

## Which one to use type or type alias

Both of them serve different purpose. Let's see an example.

Let's say that we have following code.

```elm
type alias UserInfo =
    { name : String, age : Int }

type alias Coach =
    { name : String, age : Int, sports : String }
```

Now let's write a function that gets age of the given userinfo.

```elm
getUserAge : UserInfo -> Int

getUserAge UserInfo =
    UserInfo.age
```

Now let's create two types of users.

```elm
sam = UserInfo "Sam" 24
charlie = Coach "Charlie" 52 "Basketball"
```

Now let's try to get age of both of these people.

```elm
getUserAge sam
getUserAge charlie
```

Here is
[the complete version](https://gist.github.com/neerajsingh0101/83f26c0c32c310ab01fe9a27f5bc9e98)
if you want to run it.

**Please note that elm-repl
[does not support type annotation](https://github.com/elm-lang/elm-repl/issues/86)
so you can't test this code in elm-repl.**

The main point here is that since we used `type alias`, function `getUserAge`
works for both `UserInfo` as well as `Coach`. It would be a stretch to say that
this sounds like "duck typing in Elm" but it comes pretty close.

Yes Elm is statically typed language and it enforces type. However the point
here is the `type alias` is not exactly a type.

So why did this code work.

It worked because of Elm's support for
[pattern matching](http://elm-lang.org/docs/records#pattern-matching) for
records.

As mentioned earlier `type alias` is just a shortcut for typing the verbose
version. So let's expand the type annotation of `getUserAge`.

If we were not using `type alias UserInfo` then it might have looked like as
shown below.

```elm
getUserAge : { name : String, age : Int } -> Int
```

Here the argument is a record. Here is
[official guide on Records](http://elm-lang.org/docs/records). While dealing
with records Elm looks at the argument and if that argument is a record and has
all the matching attributes then Elm will not complain because of its support
for pattern matching.

Since `Coach` has both `name` and `age` attribute `getUserAge charlie` works.

You can test it by removing the attribute `age` from `Coach` and then you will
see that Compiler will complain.

In summary if we want strict type enforcement then we should go for `type`. If
we need something so that we do not need to type all the attributes all the time
and we want pattern matching then we should go for `type alias`.

## Links

- [Human page](https://www.bigbinary.com/blog/difference-between-type-and-type-alias-in-elm)
