ngrilly

ngrilly

What is the reason for using a separate declaration for typespecs:

@spec round(number) :: integer
def round(x), do: # implementation...

Instead of “inlining” it, in a way similar to TypeScript, Flow or MyPy, with something like that:

def round(x: number) :: integer, do: # implementation...

?

Thanks for your insights!

Showing Posts 1 to 10

hubertlepicki

hubertlepicki

Typespecs in the form currently used in Elixir are not adding anything new to the language, nothing at all. They are using already existing feature of module attributes, i..e. the stuff you use with @ sign.

You can always add new syntax to the language itself, but if you do so it’s harder to remove it afterwards. Typespecs are now just data, and are treated as such, if they are ignored or changed altogether your programs will not break at all because they do not really affect your runtime.

I appreciate Elixir creator(s) keeping the language (fairly) small. Smaller is better.

ngrilly

ngrilly OP

My bad. I should have guessed, since I saw the @ sign used for other purposes as well. Thanks for clarifying this.

In TypeScript/Flow/MyPy, typespecs are just data, and are absolutely not used at runtime. The parts after the : or :: signs is just data attached to the function signature.

NobbZ

NobbZ

Types and specs in Elixir are not even used at compiletime, except that they get integrated into the compiled modules.

Then the can get evaluated using a tool called dialyzer, which is from the erlang/beam toolchain and not related to elixir (directly).

Since elixirc does not resolve types, but only stores the information of them into the module, it would telling some false story when they are inlined. As it is now, it is more or less obvious that they are an optional extra.

Also elixirs (and erlangs) type annotations are in a way powerfull that I can’t relly think a way of to express it inline while maintaining readability.

Consider this one (this is a single type and not 4!):

@spec foo(:error) :: 1
@spec foo(:two) :: "two"
@spec foo(integer) :: String.t
@spec foo(list(integer)) :: integer

Or the more classical ones;

@spec map(list(a), fun((a) -> b)) :: list(b) where a: var, b: var
@spec fold(list(a), b, fun((a, b) -> b) :: b where a: var, b: var

These specs are from the deepest areas of my mind, maybe I confused a bit syntax of them with erlang, but roughly they should show what I mean.

There are even specs much more complex you have to think about, just take a look at the contracts for all the GenServer like behaviours…

ngrilly

ngrilly OP

In JavaScript with Flow and Python 3 with MyPy, types are “inlined” but are not used by JavaScript or Python themselves. They are only used by the type checker (Flow for JavaScript and MyPy for Python 3). I don’t feel like it’s telling a “false story”. Users don’t seem confused by that approach.

But I can sympathize with your argument about readibility.

NobbZ

NobbZ

I don’t use Python or JavaScript, so I don’t know anything about that. But can you provide any examples that are as complex as my examples above?

Dialyzer types are not dependent ones, but the fact that you can specify an explicit set of return values without bothering with creating complete new types and conversion routines from that types into ordinary numbers (just as an example).

rvirding

rvirding

Creator of Erlang

It would make using pattern matching very cumbersome and the patterns would quickly become unreadable if they were to include type information.

mkunikow

mkunikow

I think I prefer separate declaration over inline. In my opinion is much cleaner.

For example in Haskell:

divideThenAdd :: Num a => a → a → a
divideThenAdd x y = (x / y) + 1

In Elm

distance : { x : Float, y : Float } → Float
distance {x,y} = sqrt (x^2 + y^2)

Also in typescript you can have separate ts files only with type declaration.

ngrilly

ngrilly OP

You’re right about pattern matching. Python and JavaScript don’t support matching. It’s probably the main reason why it’s possible to “inline” type specifications. In Elixir, it would awkward to “repeat” the type specification in each pattern. Thanks for answering.

kaashyapan

kaashyapan

Has there been any discussion/proposal over creating spec/typespecs in seperate files ?

Similar to Fsharp signature files or typescript declaration files.
https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/signature-files

I ask cos I find the type signatures in elixir tend to be more noisy.

Qqwy

Qqwy

TypeCheck Core Team

I do not think there has. The main disadvantage of moving specs to a different file is that it is very easy to forget them (and then they for instance are not updated when the functions themselves are changed).

In a language that performs full compile-time type checking it is enforced that the types and the actual signatures match, but in Elixir this is not the case.

— All posts loaded —

Where Next? Top

Trending in Discussions Top

AstonJ
As the title says, please share what you’ve been up to with Elixir. Whether that’s been learning it, looking into it, making stuff with i...
2977 94592 917
New
cblavier
Hey there, It’s been more than a year since we started using LiveView as our main UI library and building a whole library of UI componen...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
heathen
Quite interesting article Google brought me. Didn’t find any mentions about it here. What do you think in general? Would you use togethe...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
axelson
Hi there! :wave: @frigidcode and I (but mostly him) have been running an Elixir Book club, we’re almost done with Designing Elixir Syste...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
georgeguimaraes
Just published claude-code-elixir, a plugin marketplace for Claude Code with Elixir support. These are the plugins I’ve been using for my...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews