upvote
Elixir's heavy reliance on pattern matching has always made it kind of "dynamic language where you still have to think about types" vibe to it. It's also always had a spec meta-language (taken from Erlang) which a lot of people use. You should read up on how they have been implementing the type system, it's pretty interesting! I would not say it's "bolted on." It also has full inference so all codebases get the benefit of it whether you specify types or not.
reply
Yes, it is what I found works so well. It is easy to write short, specific functions in Elixir and adding Typespecs to theses functions is like typing a block of code. Within the functions everything is "easily" understandable.

Input > Enumerable.Map(Input, type-speccd functionA) > Enumerable.Map(Input, type-speccd functionB)

reply
Conversely, TypeScript is my favourite type system because it has to support the wild things people did in untyped languages.
reply
The issue with TS is that it's not really a type system, it's mostly just comments with a linter bolted on. It tries, but it's fundamentally broken in too many ways.

Here's just one very simple example, there are many more. I've checked all the strict mode options and this appears to still "typecheck".

  var x: {a: number} = {a: 1};
  var y: {a: number|string} = x;
  y.a = 'FAIL';
  var n: number = x.a; // not actually a number
Source: https://www.typescriptlang.org/play/?noUncheckedIndexedAcces...
reply
Two things to note:

1. TypeScript doesn't aim to have a sound type system. i.e. there may be things the type system accepts that are actually unsafe.

2. this is more of an issue with mutation. If those properties were marked `readonly`, then the assignment of y.a wouldn't work at all. You can also encapsulate mutation behind functions with your intended types.

I tend to write TypeScript in a "functional" or "immutable" way, and in this case, most soundness issues come from things like array index access, which can't really be solved without dependent types anyway.

With that said, TypeScript still gets one quite far *despite* soundness not being a goal of the type system. The problem is that writing imperative, mutable code will make you go through (intentionally!) unsound covariance of types. Similar issues exist for code with side effects, since TypeScript has no way to encode effects in the type system. This is why some language communities settle on ideas like "functional core, imperative shell", where the ultimate goal is absolute minimum amount of code involved in side effects and mutation, while everything else is designed to be easy to test (and, ideally, expressible with a sound subset of your type system).

reply
Haha, it is actually my least favorite statically typed lang for this very reason.
reply
I agree. The sheer amount of flexibility it provides makes it both hard to use/read and also not particularly safe/sound. No other type system in existence allows you to be as incoherent as TS.
reply
You didn't like Purescript? It looked pretty cool to me. Its main competition back in the day was Elm, but Typescript has now taken over. From a distance Typescript seems to have too many gaps. I haven't used it though.
reply
The Lustre [0] web framework in Gleam was directly inspired by Elm.

[0] https://github.com/lustre-labs/lustre

reply
I think TypeScript can feel like there's too many gaps because not enough people take it seriously enough to truly learn it. Hardly anyone reads a book about best practices/design the way many do about C/Java/Rust.

It's actually a very powerful tool when used thoughtfully. Although it wasn't the first structurally typed language I tried, it's the one that made me fall in love with structural type systems

reply
I like the strutural typing as well. But I hesitate to use TypeScript because AI tells me this:

It Catches: Mismatched function arguments, missing object properties, and typos in variable names.

It Misses: Invalid JSON from an API, unexpected database outputs, and bad user input.

reply
You use Zod if you want runtime features. I'd say it's pretty industry standard. On the type level there's no reason it couldn't account for any of the examples you pointed out. And since Zod supports all the expressiveness of the actual language, you can certainly have those as runtime checks

I would also just like to point out that the "It Misses" your robot pointed out aren't actually flaws with TypeScript but flaws with JavaScript.

reply
[flagged]
reply
I think Elixir is taking a very mature path to typing. No type-annotations (yet) just type inference from existing language constructs like function guards and pattern matching. Also trying to minimize false positives, only giving type errors when it would provably crash at runtime.
reply
I agree with you but an alternative view, "Why are gradual static types so great?" https://www.benkuhn.net/gradual/
reply
Pretty weak argument as most points aren't inherent to gradual typing at all.
reply
I've experienced this, but it's mostly because languages like Python and TypeScript give you way too many escape hatches. I get the intent: allow devs to convert their code base slowly. But in practice it just lets developers opt out of the benefits of typing to "save time" in the short run.
reply
Once you are squarely in a Typescript program and not a "Javascript program gradually adopting Typescript", it would be a good idea to enable Strict mode which forbids implicit-any, effectively meaning the only places you can omit type declarations is where the language will infer the type. Typescript for instance does not infer types of function arguments via their usages (like Flow does), which means in strict mode you must explicitly provide a type for all arguments within a function declaration.

I used to be a bit of a pragmatist when it comes to strict mode, but over the years that has subsided, nowadays I think it is plainly obvious that all Typescript programs should use strict mode unless there's a damn good reason. And I'm not sure there are any legitimate damn good reasons.

True there is no ability to forbid an explicit-any type declaration, though.

reply
There is @typescript-eslint/no-explicit-any.
reply
More generally you can use "no-restricted-syntax" rule to forbid almost any type of syntax by matching AST against CSS-like selectors.

https://eslint.org/docs/latest/rules/no-restricted-syntax

https://typescript-eslint.io/play/

reply
I’ve never had a real problem with developers opting out. It’s not that hard to enforce coding standards.

The real problem with Python is the inexpressiveness of its type system and the mess of typed dicts, dataclasses and pydantic classes.

TypeScript may fail narrowing here and there or require a superfluous assert, but usually writing properly typed code, especially with zod, is the path of least resistance.

reply
Well now Claude will add the types for me, so I don't need to use escape hatches
reply
As long as you're fine with the types being semantic gibberish because all agents I've used take the lowest effort approach to make the error go away.

You probably have the same logical type duplicated in 3+ different places (at least partially), including inline casts using type literals like "maybeCat as { meow(): void }"

reply
So far I've seen it actually do the types well when I tell it to add types. But even if it didn't, I wouldn't care, it's just to check a box.
reply
I haven't tried that but so are you saying I could basically code in JavaScript and then ask Claude to turn it into TypeScript?
reply
Yeah, I've done it with JS, but more often with Python.
reply
It also takes a long time for the ecosystem to catch up. It can be hard to retrofit static types over something that wasn’t built with them in mind
reply
I keep getting baited by these comments so this is the last one I'll respond to, lol.

Elixir is always been sort of a "typed dynamic language" due to how baked in pattern matching is. Any good Elixir developer has always been thinking about types anyway, it's almost impossible not to.

reply
That’s a good point! And I suppose you don’t have willy-nilly reassignment of properties like you do in ruby/php/js.
reply
Also, as I kept forgetting to mention, there are no overloaded operators (`+` only works on numbers, for example... unfortunately it does work on both ints and floats but that's another story). The one pain point is that comparriason operators works across all types, but the compiler has already been warning against doing that for at least a year now.
reply
Ok dang. Well. I guess I have no reason not to dive fully into the elixir now.

I’ve toyed around with it a handful of times and I really like it. I like the clojure-ey immutability and threading operators and such. And of course I’ve heard so much about the magic of the BEAM and the phoenix framework. But between typescript and clojure I’ve never felt like I needed anything else.

But if the type system is pretty good, that’s a huge plus over clojure in my book.

reply
So JavaScript didn't work well and is successful?
reply
To be fair I think the success of JS is in spite of it not working super well
reply
JS was designed well. Got a lot of things right that others copied later, and also made improvements without breaking compatibility. And the random weird things like [] == 0 don't come up much in actual usage.
reply
Well, JavaScript isn't a typed language, so the answer to your question can't even be "no".
reply
It was poorly bolted on in Python. Well I dislike types to begin with, but aside from that, Typescript somehow did it better.
reply
> Typescript somehow did it better

I don’t think JavaScript’s syntax was ever designed with the idea that TypeScript would one day exist. Yet somehow it feels like it left the perfect open spaces for TS to later occupy.

reply
They did get lucky with that. The Python type syntax ended up being similar, but the implementation of type-checking is confusing, also it was annoying how you needed to import the types of basic collections for a while.
reply
Typescript is brilliant and should be carefully studied by anybody introducing a type system to a single typed ("untyped") language.
reply