Hacker News new | ask | show | jobs
by Merg 2491 days ago
As far as I don't like the "Angry Lisp Drunk Haskell" version of TS e.g. loads of `<` and '>' mixed with functional concepts from half of the Haskell, which makes understanding code harder than necessary.

Typescript is one of the rare good things in javascript. You have to understands JS, because there is always gun pointed at your foot, waiting to blow you away. Still TS makes this gun, a little bit harder to trigger. You cannot just write Java in it and cross your fingers.

Typescript gives you pretty good docs most of the time for free. Only problem is when author of code used `any` type or `Angry Lisp` version of it. Interfaces, enums and field access and typedefs are godsend.

In defense of TypeScript, your example looks like casting `void*` in C. Well typed `JSON.parse` would be pretty complicated and require runtime-machinery.

Only thing I dislike about TS is lack of proper `optional` types. I know the '.?' operator is coming, but still.

2 comments

They have the unknown type since 3.0, which will force you to write runtime validation to satisfy the type checker.

It’s very helpful for dealing with untrusted/uncontrolled data.

> your example looks like casting `void *` in C

In practice, that's a pretty good approximation, except that in C, such a cast sticks out like a sore thumb, whereas something like `const o:Foo = getSomeDataSomehow()` looks the same for both a matching concrete type as it does for a cast from `any`.

The thing with type systems like Typescript/Flow is that there are both structural types and nominal types, and _some_ ability to refine nominal types based on their structures, but then people think they can extrapolate that limited capability to ends that the type system doesn't really support.

The return type of JSON.parse can very neatly be expressed with a recursive ADT (e.g. something like `type JSON = string | number | boolean | null | {[key: string]: JSON} | Array<JSON>`), and TS/Flow do have the ability to refine ADTs, e.g. `if (typeof x === 'string') x.toLowerCase()` is perfectly sound. Why that's not the default is a bit mind boggling IMHO.

What doesn't make sense is to assume one can cast a generic structural type to a random concrete nominal type using the "I know better than the compiler, let me cast" escape hatch mechanism, and then simultaneously omit the runtime refinement checks that they are responsible for writing, when they voided warranty through the cast.

But it's a heck lot harder to explain that they are writing unsound code in this case, because "hey look my type coverage is high, it must be sound!"

TL;DR: TS/Flow aren't silver bullets, but as usual, people tend to cling on to the brand as a social proof of "safety", rather than actually taking the time to understand what actual type safety is all about.