Hacker News new | ask | show | jobs
by Vaguely2178 1124 days ago
> If I would level criticisms at dialyzer it would be its sometimes difficult to read warnings, it’s speed (despite being multithreaded) and the race conditions in the VS Code plugin (which is looking for extra maintainers – if I had time I would help).

One of the advantages of TypeScript is that VSCode is written in TypeScript, and both VSCode and TypeScript are developed by the same company, so there's a really nice synergy there. I imagine Kotlin users feel the same way using Jetbrains products, and Swift users feel the same way about XCode.

Dialyzer looks interesting, but I can't imagine giving up on the expressiveness of TypeScript. Some of the things you can do with generics, mapped types, intersection types, template literal types, conditional types, and utility types are almost mind boggling. It's difficult to reap all of the benefits of static analysis without some of these advanced type operators. The type manipulation section of the TS manual is really underrated.

Someone for example wrote an SQL parser in TypeScript that requires no runtime code [1]. It can infer the types of an SQL query's result based on an SQL string without any runtime code execution. There was a similar project where someone built a JSON parser entirely using the type system [2]. There's also an ongoing discussion on Github about the the fact that TypeScript's type system appears to be a Turing-complete language with some other cool examples [3]. My point is that the type system is incredibly expressive. You rarely run into an idiom that can't be typed effectively.

[1] https://github.com/codemix/ts-sql

[2] https://twitter.com/buildsghost/status/1301976526603206657

[3] https://github.com/microsoft/TypeScript/issues/14833

1 comments

The SQL stuff sounds cool, but Ecto is so expressive I don’t even need to resort to raw SQL like I do in other languages. Elixir typing can handle a subset of intersection type which is rather niche, and of course handles union types which are more prevalent. Genetics and inheritance are replaced with a more permissive style of polymorphism with Elixir behaviors and are also part of the typing system.

All languages have their own flavor, and their own pros and cons, and if the advanced types of Typescript work for you, then great! In my own experience, I have found Elixir and it’s typing capabilities to work well for me

> The SQL stuff sounds cool, but Ecto is so expressive I don’t even need to resort to raw SQL like I do in other languages.

The SQL example I linked to isn't something you'd use to interact with a database in production, for that you'd probably reach for an ORM like Prisma. I was just trying to demonstrate the level of type inference you can achieve with TS. Going from a pure string of SQL or JSON to a concrete type without actually executing any runtime code is pretty crazy.

> Elixir typing can handle a subset of intersection type which is rather niche

I personally use intersection types quite a bit. If union types are like the logical or operator, then intersection types are like the logical and operator. Being able to define a type that combines one type and another is not a niche workflow for me.

> In my own experience, I have found Elixir and it’s typing capabilities to work well for me

Can't argue with that! Everyone has their preferences.

> Going from a pure string of SQL or JSON to a concrete type without actually executing any runtime code is pretty crazy.

Going from a JSON string to a type for it is actually one of the easier examples of inference I can imagine. JSON is a data description format in which all the base types are syntactically distinguishable, it has no variables, no arrows (i.e. functions), no generics. In the topic of type inference, you can't have a much easier example.

SQL is more complex, indeed, but still doesn't seem too crazy if you have access to table schemas. It's also a matter of whether triggers and stored procedures are taken into account, but I assume they're not.

There's a lot of prior art described in literature as well as practical programming implementations with much crazier, yet successfully working type inference.

I just want to make sure we're on the same page here. The JSON example I linked to isn't inferring the types of JSON that's already been parsed and deserialized, that would be trivially easy in any language (including TS). If I have an object that's been parsed from JSON, I can just use the typeof operator in TypeScript to infer the type of that object.

The example I linked to is taking a serialized JSON string, and parsing the literal characters in the string (characters like double quotes, commas, whitespace, etc) into a type, purely using type annotations. And the structure of that JSON can be of arbitrary nested depth.

All of this is accomplished using template literal types which allow you to make assertions about the contents of a string. In TypeScript you can assert more than just "this value should be a string". You can make detailed assertions about the structure of strings, and that's what allows these parser demos to exist.

When you combine these template literal types with recursive types, conditional types, and TypeScript's infer keyword you can do some pretty interesting type level programming.

Just to further demonstrate the point, there's an interpreter for the BF programming language, written entirely using TypeScript type annotations [1].

> There's a lot of prior art described in literature as well as practical programming implementations with much crazier, yet successfully working type inference.

Has any of this been demonstrated in Elixir?

[1] https://github.com/sno2/bf

I’m not the GP, but already Elixir can already accomplish compile time text processing with metaprogramming (like it does for inline html templating for ‘heex’ functions and files) and it’s not a huge stretch for it to be able to call a JSON parser on any string knowable at compile time and convert it into a type. That it hasn’t been done yet is probably because no one has deemed to worthwhile to implement. It does sounds cool though.

Metaprogramming is also why generics aren’t really needed in Elixir or Erlang. All specializations boil down to their reified types using macros

> I’m not the GP, but already Elixir can already accomplish compile time text processing with metaprogramming (like it does for inline html templating for ‘heex’ functions and files)

It's not the compile time text processing that's interesting, it's the fact that this compile time code can yield incredibly detailed types, and the fact that it's all done purely using type annotations. Almost every language that's used to build websites has some sort of server side templating language where you can sprinkle some code into your html templates.

> That it hasn’t been done yet is probably because no one has deemed to worthwhile to implement.

Maybe, or maybe it's less feasible without an advanced type system. The final version of the JSON example we're talking about ended up being 61 lines of code. Without some concrete Elixir code to inspect, this conversation is becoming very abstract.

Honestly even if some of this were possible with metaprogramming, my intuition is that it would be much more verbose and complex. I feel like if I tried to implement all of the features of TypeScript by mucking around with an abstract syntax tree using metaprogramming, I would end up with a difficult to maintain crude approximation of the real thing. I don't think we're giving compiler developers enough credit by saying everything they've worked on can be replaced with a quick macro. José Valim's blog post on static typing ended with an announcement that they've sponsored a PhD student to work on these problems.

After two days of discussion, I think we're reaching a bit of an impasse. Honestly just use what works for you!

> Going from a pure string of SQL or JSON to a concrete type without actually executing any runtime code is pretty crazy.

Elixir/Erlang might already be able to do something like this with metaprogramming. It’s certainly possible to generate and run Elixir at compile time, and map types are already a good superset for JSON objects, so a compile time JSON to map could then provide an inferrable type. I think someone more savvy with Elixir would know more. I’d certainly not something that I’ve needed.