Hacker News new | ask | show | jobs
by earthly 2327 days ago
I still don't understand what pulls developers to Typescript. The examples given show major flaws in this (duck)type system. That it works when you don't use the 'any' type and when you know how to avoid all the edge cases and workarounds, I know. But when I see an example like this:

  const shasta = new Cat("Maine Coon")
  printDog(shasta)
  > Dog:Maine Coon

I see a huge red flag. Coming from C/C++ it looks like a joke. Why are all these front-end static type fanatics not more interested in Dart, Purescript, Elm, etc..?
9 comments

Because you can get some decent typing with some compiler help AND leverage the entire node/js eco system super easily. Which is kind of the whole point.

As someone that's done c/c++/c#/lua/js/ts I've found typescript to be really awesome because it differentiates the types from the objects. Which has given me a much better appreciation of typing rather than the traditional OOP everything.

What do you mean by “differentiates the types from the objects”? Could you maybe offer an example comparing TS and C#?
in typescript I have something like

type theThing = { thing1: string, thing2: string };

and the actual object: const thing:Thing = { thing: 'hello', thing2:'more hello' };

"Thing" is not an object, I can't do Thing.new() etc. If I use a class in typescript it behaves just like you would expect C# / Java to.

This allows some really fun stuff with unions where I could do something like

const operateOnThings = (thing: Thing | Thing1 | Thing2) => { //do something based on what kind of thing it is }

Or I can build other types off of it like : type newThing = Pick<Thing, 'thing1'> & { newerThing: number};

Which is something I would have to do a lot of work with interfaces with in order to implement in C#. (I haven't done C# in a few years but I do love the hell out of it).

It just means that structural types are the default and you need to opt in to nominal types, when necessary: https://www.typescriptlang.org/play/?ssl=13&ssc=1&pln=13&pc=... (there are other ways as well)

In something like Java, it's the opposite: you get nominal types by default and you need to opt in to structural types (via interfaces).

Because TS is built on a duck typed language, tons of existing libraries would break if they had to declare explicit nominal types as arguments. Or you'd need to add custom interfaces for each library you use. Structural typing is what you want 99% of the time.

I think that Flow’s approach of using nominal types for classes and structural for everything else makes more sense. Are there really cases you expect classes to be structural types?
Objects in OCaml are all structurally typed.
Java interfaces are not structurally typed, are they?
No but it's the closest available. Two classes C1 and C2 that both implement interfaces I1 and I2 can be said to have a common structure. That is, if they both implement I1 and I2 then they have that structure in common.
Yeah but that’s still fully nominal typing, you can’t implement the interface implicitly, it has to be identified by name.
I've never used Typescript, but I don't think these are really 'major' flaws. That's just my perspective as someone that's being doing FE for over a decade and picks this stuff up fairly quick. Obviously it's more of a problem for newbs that probably aren't going to read that paragraph about discriminated unions and grok it straight away.

Having said that, I absolutely hate the ending of this blog post. I see blog writers do this all the time. He's just given three detailed, concrete negatives about Typescript, given enough information to infer that these quirks could be problematic for beginners and cost your team time and resources. Then at the end, he suggests that you use Typescript and waves it all away with some ambiguous bullshit about how static typing saves you a bunch of time.

There's so many of these claims that are just taken as common knowledge/best practices, that everyone treats as absolute truth that overrules everything else, even good concrete examples. I've been building entire apps myself for over a decade now, using both plain and typed (flow) JS, and every time I've seen somebody try and elaborate on how static typing saves you all this time, it's some pissant todo list bug that I would have solved in 5 seconds with plain JS.

Try working with a large 5 year old JS codebase that's been hammered on by dozens of devs. The problems are no longer just pin point bugs but a systemic lack of modeling.

Static typing is not that much about preventing bugs but more about forcing the code to operate over a well defined model.

Can you write good code without static typing? Yes. Can you scale and maintain it in a large organization, probably not.

It’s structural static typing, a perfectly cromulent class of type system, and much more easily compatible with dynamics types.
Structural typing and actual first class union types in typescript are better than basically all the ML-based languages.

Dumb example: imagine you had

Animal = Dog | Cat

Person = Plumber | Driver

If you want a list of “stuff” in your system , in typescript you just say you have Person | Animal.

In ML languages you would need to introduce an Either type so you’re working with Either Person Animal.

So now in your code you’ll need to introduce a bunch of Lefts and Rights. And if you end up needing to compose you’re introducing even another layer of Lefts and Rights. And you don’t get much of any or the inference capabilities of TS to just do this for you.

ML languages don’t have first class unions, they have ADTs, which introduce difficulties and lead to classic type safety weirdness like “why can’t I write a function that only accepts one ADT variant??”

Typescript resolves a lot of these, do you end up with a much better local maximum for typechecking IMO.

Typescripts type unsoundness means you unfortunately can’t really implement return type polymorphism though...

What you are describing is still an ADT. It's just a different syntax.

Indeed, your examples of the TS syntax are more convenient than ML, but that is reversed when going the other way, and decomposing the types into smaller sums instead of composing.

> I still don't understand what pulls developers to Typescript... Coming from C/C++ it looks like a joke.

Remember that this all compiles down to JavaScript where it's all dynamic/weak types. Someone coming from C/C++ should definitely appreciate TypeScript over just plain JavaScript.

Because TypeScript is a superset of JavaScript and works directly with existing JavaScript code.

It’s the same reason that there is any interest at all in MyPy for Python, Sorbet for Ruby etc.

Why not embrace Elm or Purescript?

Because those are a massive paradigm shift. TS is easy. You can sell it as “JS but better. If all else fails you can always resort to any”. Selling Elm to someone who only ever used C# is very hard. I’ve tried.

It is also familiar enough for the hordes and horses of C# and Java devs in your company. It’s even an MS product. Enterprise yay!

A safe choice. You won’t be crucified if it goes wrong.

It’s sad, I know.

TypeScript does not offer perfect typing, but on the other hand, your example is wild in such a way, that I don't think I would ever encounter it with a professional team of developers.

I.e. it would be quickly caught in a review, and the offending developer would have to bring cake the next day.

Yes, TypeScript is not perfect, but we take what we can get