Elixir is dynamically and strongly typed

Learn Phoenix LiveView is the comprehensive tutorial that teaches you everything you need to build a complex, realistic, fully-featured web app with Phoenix LiveView. Click here to learn more!

In a recent post I made the case for why Elixir’s lack of static typing isn’t as big of a problem as some people insist. I stand by my words - but while we’re on the subject, let’s clear up a common misunderstanding.

Whenever people are debating dynamic vs. static languages, I inevitably see at least one comment about “strong typing”. “Elixir isn’t strongly typed”, someone will say - but this is wrong. Elixir might not be statically typed (yet), but it absolutely is strongly typed. They’re not the same thing.

Since these two concepts are so frequently confused, allow me to clear things up:

Dynamic vs. static typing

Elixir, like Ruby, Python and Javascript, is a dynamically typed language. This means that a variable’s type - integer, string, map, etc. - is checked at runtime, not compile time.

This contrasts with statically typed languages like Java, where a variable’s type is declared (or inferred) at compile time. For example, the following line of Java defines a variable x and explicitly tells the compiler that x’s value is an integer:

int x = 5;

Now if you try to assign a non-integer value to x, you’ll get an error when you try to compile:

int x = 5;
// This causes a compiler error:
x = "Not an integer";

Elixir doesn’t have explicit type declarations, and the Elixir compiler doesn’t care if you change a variable’s type post-declaration[1]. So the following snippet is perfectly valid Elixir (and incidentally would also work in Ruby, Python or Javascript):

x = 5
x = "Not an integer"

(As of early 2024, the Elixir team is exploring the possibility of adding a static typing system to a Elixir, but despite recent announcements it’s not with us yet.)

Strong vs. Weak typing

Dynamic typing isn’t the same thing as weak typing, also known as loose typing. Elixir is dynamically typed, but it’s not weakly typed - it’s strongly typed.

Strong typing means that Elixir won’t perform implicit type conversions at runtime. For example, the following Elixir code is invalid, because the string concatenation operator <> can only accept binaries (i.e. strings) as arguments, and 2 is an integer:

iex> "1" <> 2
** (ArgumentError) expected binary argument in <> operator but got: 2

It is possible to cast (convert) an integer to a string in Elixir, but we must do it explicitly; the compiler isn’t going to do it for us:

iex> "1" <> to_string(2)
"12"

Ruby is also strongly typed:

irb> "1" + 2
# no implicit conversion of Integer into String (TypeError)
irb> "1" + "2"
# => "12"

Javascript, however, has weaker typing. If you try to “add” a string to a number in Javascript, it’ll assume you’re trying to concatenate strings, and will cast the number to a string for you:

1 + "2"
// => '12'

Strong typing is frequently confused with static typing, but they’re not the same thing.

The pros and cons of dynamic typing

The main advantage of dynamic typing is that it makes your code more flexible and less verbose. It’s usually faster to write, but it also makes it easier to introduce typing errors that you don’t notice until your code runs - for example, passing a string to a function when you meant to pass an integer.

That’s why some people say that they can’t live without static typing. They need the safety and security it provides, so they say, especially on big codebases with a big team, and this scares them away from dynamic languages like Elixir.

I’ve already made the case that, at least where Elixir is concerned, these fears are overblown, so I won’t repeat myself here. All I’ll say for now is: if you’re going to criticize Elixir’s typing system, at least get your terminology right! And while you’re at it, stop saying “PIN number”.

Want more posts like this in your inbox?

No spam. Unsubscribe any time.