Hacker News new | ask | show | jobs
by forgotmyoldacc 1600 days ago
I might just be not as intelligent as the average TypeScript developer, but I find the complexity with the type system off-putting. There's 5 different ways to type something, and learning a new type language isn't what I wanted when I just needed my JavaScript to be typed.

It's too bad Flow has lost the typed-JS battle, I find the syntax to be a lot easier to use.

10 comments

Someone created a very nice curated list of advanced Typescript videos. [0] After watching and working through them, I have not been stumped with more complex typing problems.

[0] https://www.youtube.com/playlist?list=PLw5h0DiJ-9PBIgIyd2ZA1...

The key is to ignore 90% of TypeScript's features in the average application-level codebase. I avoid even using named generic types, much less conditional types etc.

Unfortunately, having all that power available is necessary because it has to be able to reasonably describe a highly-dynamic language. The more dynamic your JS is to begin with, the crazier your types will have to be to make sense of it. But most of that craziness can be avoided if you write straightforward logic with straightforward data structures to begin with.

To expand on this, as someone with a deep sense of Typescript's features I start to flag them if I see them in PRs to applications. A lot of Typescript's features are for other people's code or for building blocks to smarter features (conditional types are interesting sure, but they sing in things like ReturnType<T>; you don't need to know the conditional type underpinnings to use the higher level ReturnType<T> feature).

I've had to break out some wild types to describe JS modules I've needed. If I need such things inside a TS application I control, I often see that as a failure to write clean/concise code in the domain language of the application itself rather than some "ideal" abstraction that may not matter (and I expect will eventually crumble into unreadable tech debt).

> and I expect will eventually crumble into unreadable tech debt

Or crumble when tsc tries to follow them ;)

I’ve sometimes found, perhaps for the better, that when I get too creative with types the typescript compiler will at some point just not be able to follow what I’m trying to tell it any more. Even though my types are correct, theoretically, it will just sort of tip over. That usually serves as a good sign that I shouldn’t be trying to do what I’m doing at all.

> and learning a new type language isn't what I wanted when I just needed my JavaScript to be typed.

Well, good news, you can use Typescript's compiler as a Js static code analyzer without writing a single line of Typescript!

Strongly disagree.

It is OK if you prefer no solution to some complex typing needs that are solved with complex syntax in Typescript.

Most of Typescript is optional.

It's not trivial to think of simpler alternatives to much of the problems Typescript is tackling.

(And if you have any simplifying syntax suggestions that don't break typing it will be interesting to read)

> but I find the complexity with the type system off-putting

Yeah, is it. But "complexity" is fine:

    Complex is better than complicated.
         - [Zend of python](https://www.python.org/dev/peps/pep-0020/)
What is a big trouble is when the complexity is NOT intentionally designed (ie: in languages like oCalm, Rust, Coq...) but instead the type system is a lie that bring "complications":

    //A bad language, like JS, with both complexity AND complications:
    [] - {}; // NaN
    
Humans can deal with complexity if is part of a intentional design (example: APL), but what we dread is when is accidental...

    [] - {}
is a fatal typescript error[0]. A well configured linter can also catch out similar nonsense, but [] - 2 does get past the compiler.

The TS Compiler can atleast stop you from doing nonsense like applying operators to types where they don't make sense. Of course, it'd be better if JS just threw an error or something, but atleast TS can stop you.

[0]: The right-hand side of an arithmetic operation must be of type 'any', 'number', 'bigint' or an enum type.ts(2363)

I’m curious about the example of unintentional complexity and type system lies in Rust?

Or did you mean to say that oCaml, Rust, and Coq have intentional design complexity?

> have intentional design complexity?

yes, more like this (in special Rust, that deal with many challenges like system programming, safety, etc).

Typescript can type all your existing JS, but you're right it's crazy complex. TS only becomes manageable when you stop treating the compiler as an add-on and treat it as a guide.
You almost never need to reach for advanced typing unless you're writing a generic library.
Check out Hegel[0], it uses Flow syntax, it's compatible w/ .d.ts type definitions and has a smarter type inference model than both TS and Flow IMHO[1].

[0] https://hegel.js.org/

[1] https://www.reddit.com/r/JSdev/comments/nl4ccq/is_flow_movin...

I absolutely agree. But I assume that at least some of the complexity also comes from what JS can do so typing some things might inherently be complicated. But trying to type an arrow style react component with generics in it‘s props has been incredibly tough an I am absolutely sure I didn‘t do it correctly (tsx also getting in on the fun is another complexity making just figuring out how to even write certain things challenging).
Ha. It's not you. It's a shit show everything is a afterthought. It's incredibly inconsistent and clunky all over. I just don't try to get carried away with typing stuff too smartly.

Most of this is just the way the language evolved, along JavaScript. I wish they'd abandon the "JavaScript superset idea" and cleaned up the language.

Make the common case simpler and more straightforward, drop everything exotic, it's not practical nor strictly necessary.