I didn't mention OO in general and specifically Java and C#. JS is OO deep down, nobody is denying that, but it's not OO as in Java/C# where writing a function without a class is not idiomatic.
> "Class" and some other changes make the existing OO features usable in a way that won't have your successors cursing you for your "clever" use of prototypes
That's a strawman, you can write "clever" code with classes that will make your successors curse you just like you can write plain and readable code with prototypes.
> you can write plain and readable code with prototypes.
It's really far from being ergonomic, unless you're basically just using JS objects as structs. Otherwise you're dancing around its pitfalls and limitations—visibly, in code, not just in your head—to express things that are very simple and clear in pretty much every other commonly-used OO-supporting language.
> I didn't mention OO in general and specifically Java and C#. JS is OO deep down, nobody is denying that, but it's not OO as in Java/C# where writing a function without a class is not idiomatic.
Sure, JS is multi-paradigm, like tons of other languages. Its early design, and early use in the wild, hints at "Imperative with quite a bit of OO and a sprinkling of functional for things like callbacks" being more-or-less its intended style, but of course that can (and has) changed over time, because the core language has half-decent support for all three styles.
Incidentally, I've yet to see a TS codebase that ties itself in knots to avoid defining a function outside a class, to avoid treating functions as first-class when it makes sense to, or even to avoid a little imperative code outside of objects, here and there. They may exist, but I haven't seen it. I have seen a lot of code using HOFs to the point of absurdity, while passing big objects around to a bunch of functions and pretending that's "more pure" than putting those related functions on a class for that object. Or trying to shoehorn runtime-checked immutability into the language, at a performance cost for end users. Or writing their own weird, crippled form of objects in a language that already has them so they can keep things "pure" and let people keep avoiding the Class keyword for... whatever reasons they want to do that (React Hooks).
> It's really far from being ergonomic, unless you're basically just using JS objects as structs. Otherwise you're dancing around its pitfalls and limitations—visibly, in code, not just in your head—to express things that are very simple and clear in pretty much every other commonly-used OO-supporting language.
That might be because I've started OO with JS and mostly did some with it, but in my experience it's fine. I do tend to not use OO as in "object mutating themselves" much though, outside of cases where it's a great fit like a database connection.
> Incidentally, I've yet to see a TS codebase that ties itself in knots to avoid defining a function outside a class, to avoid treating functions as first-class when it makes sense to, or even to avoid a little imperative code outside of objects, here and there.
I haven't seen big codebases like that, but I've had a few collegues coming from Java/C# start every piece of code by writing a class, usually in a "kingdom of names" styles. I'm worried that TS may enable these people even more in the future.
> I have seen a lot of code using HOFs to the point of absurdity, while passing big objects around to a bunch of functions and pretending that's "more pure" than putting those related functions on a class for that object. Or trying to shoehorn runtime-checked immutability into the language, at a performance cost for end users. Or writing their own weird, crippled form of objects in a language that already has them so they can keep things "pure" and let people keep avoiding the Class keyword for... whatever reasons they want to do that (React Hooks).
I'm not defending "functional" (as in ML/Haskell) JS and agree with you here. If people want to do functional programming, there's OCaml, Elm, F#, Scala.js and ReScript, no need to shoehorn that into JS. I think that's an antipattern, just like doing OO everywhere for the sake of it.
Haha, cool, I think we're actually in agreement. I think JS works best if you embrace its multi-paradigm nature, and attempts to make it either Java or Haskell would be horribly misguided, even if those were both better languages, because the language doesn't really support the things that make going purely into either of those paradigms attractive—with or without TypeScript doing a little compile-time type checking on top.
> "Class" and some other changes make the existing OO features usable in a way that won't have your successors cursing you for your "clever" use of prototypes
That's a strawman, you can write "clever" code with classes that will make your successors curse you just like you can write plain and readable code with prototypes.