News for hackers. Stuff that matters.
Re:TypeScript’s quirks: How inconsistencies make the languag... by twotwotwo on Saturday February 01, 2020 @01:59AM (#22209164)
These can make sense if you think of TS as better-checked JavaScript, not as a from-scratch design for a statically typed language. Excess property checks catch a common JavaScript bug (typoed property names), structural static typing matches the dynamic duck typing JavaScript authors had already been working with (though I see how nominal would be useful), and it's awesome they found a workable hack for discriminated unions where the code and objects look like what you'd do in vanilla JS, but checked (and requiring the class to have a specific structure seems fine as limitations go).

I get how folks coming from "natively" static type systems could find all this weird, but I think by targeting "JS but with better checks" instead of a more fundamental redesign, the TypeScript crew have managed to build something that can get traction where other efforts have not.

Re:TypeScript’s quirks: How inconsistencies make the languag... by Findeton on Saturday February 01, 2020 @03:55AM (#22209529)
As someone that uses the language everyday, these are real quirks on the language, but they are not showstoppers. The benefits of using exactly the same language in front-end and back-end, with shared types and everything, largely offset the small quirks.

However sometimes I kinda miss some functional stuff that you can for example find in Scala or Rust, like pattern matching. Specifically, we've had experience using/developing an input validation library for the backend in Typescript (https://github.com/StrontiumJS/Framework/) that is composable and also returns the correct type in one go. We used a lot of try catches for that, but that makes validation slow. So we started using "maybe promises" which are similar to Scala's Futures with Success/Failure. But the fact you don't have pattern matching in Typescript like in Scala makes it a bit ugly.

Re:TypeScript’s quirks: How inconsistencies make the languag... by firethief on Saturday February 01, 2020 @11:32AM (#22211379)
Have you considered OCaml with BuckleScript or js_of_ocaml? The language that inspired Rust's nods to FP can be compiled to mostly-idiomatic Javascript.
Re:TypeScript’s quirks: How inconsistencies make the languag... by Fannon on Sunday February 02, 2020 @03:25AM (#22215862)
Pattern matching seems to be a current proposal, also driven by Microsoft: https://github.com/tc39/proposal-pattern-matching
Re:TypeScript’s quirks: How inconsistencies make the languag... by Shacklz on Sunday February 02, 2020 @03:22AM (#22215855)
Pattern matching is definitely something I also miss. For input validation and Optional/Either types, io-ts/fp-ts (https://github.com/gcanti/io-ts) fulfill my needs perfectly, especially io-ts is something I can't recommend enough. Saved me so many headaches from sudden breaking changes in APIs we consume.
Re:TypeScript’s quirks: How inconsistencies make the languag... by gazarullz on Saturday February 01, 2020 @05:47AM (#22209852)
You should try using computed propeties, it's the closest/cleanest way to pattern matching until tc39 will pass the pending proposal.
Re:TypeScript’s quirks: How inconsistencies make the languag... by ketzo on Saturday February 01, 2020 @03:01AM (#22209339)
Yup. Rather than bringing 100,000 devs from one typed language to another, Typescript brings 1,000,000 devs from untyped to typed.
Re:TypeScript’s quirks: How inconsistencies make the languag... by bt4u on Saturday February 01, 2020 @04:41AM (#22209652)
There's no such thing as an untyped programming language that's used in the real world. JavaScript and typescript definitely aren't. Maybe you mean dynamically typed
Re:TypeScript’s quirks: How inconsistencies make the languag... by Sharlin on Saturday February 01, 2020 @08:30AM (#22210395)
This is just a question of semantics. In mainstream programming language jargon it’s ”dynamically typed”, while in (applied) type theory it’s ”untyped” or, perhaps more accurately ”monotyped” or ”unityped”, because types are fundamentally invariants of a program that can be verified without executing it.
Re:TypeScript’s quirks: How inconsistencies make the languag... by heavenlyblue on Saturday February 01, 2020 @10:31AM (#22211000)
There’s always that “intellectual” who would say something smart while being absolutely wrong.
Re:TypeScript’s quirks: How inconsistencies make the languag... by cloverich on Saturday February 01, 2020 @11:05PM (#22215070)
Structural typing has the benefit of making it easier to code to an interface and reminds me of Go. If you have a function that requires a method off a class (say, `poop`), then rather than declaring it to accept `Cat | Dog` (or overload it, in e.g. Java), you code it to accept an object with a single function (`pooper: { poop: VoidFunction}`). Then anything that implements it can use it, testing is typed and easy, and changing the class is less likely to affect the consuming method.

Its such a powerful pattern, I'm a bit surprised to see so much negativity about it. I'm aware there's alternatives and reasoned opinions, but I bet a significant number of people have never seen or programmed in this style and aren't aware of what they are missing. For me, I can't imagine using another typed language that doesn't support implicit interfaces in this manner.

Re:TypeScript’s quirks: How inconsistencies make the languag... by kazinator on Saturday February 01, 2020 @03:08AM (#22209372)
If you can pass a Cat to a Dog function, where is the better checking?

That would be one of the hello-world test cases for a type checker bolted on to a dynamic language.

That type checker itself has introduced the syntax for declaring Cat and Dog classes; yet is neglecting to do the obvious with it.

Re:TypeScript’s quirks: How inconsistencies make the languag... by MaulingMonkey on Saturday February 01, 2020 @03:38AM (#22209480)
Note that you can only pass Cat to a Dog function if:

* All fields of Dog are also present in Cat, with compatible type signatures

* All functions of Dog are also present in Cat, with comaptible type signatures

"compatible type signatures" does seem to leave some suprising co/contravariance holes still when using wider union types, but C#/Java arrays also have co/contravariance holes and we don't automatically write off their entire type systems because of it. Or, well, at least I don't ;).

As a meaningless point of ancedata: Making these types sufficiently equivalent to fall through this type safety hole appears to be rare enough that I've never done so by accident - allowing me to be suprised by the article's example of passing a class Cat to a class Dog-accepting function being legal. While typescript has never been my primary dayjob, it's been a significant secondary part of my dayjob and hobby junk.

(EDIT: Minor clarifications)

Re:TypeScript’s quirks: How inconsistencies make the languag... by Kinrany on Saturday February 01, 2020 @06:45AM (#22210017)
Re:TypeScript’s quirks: How inconsistencies make the languag... by carlmr on Saturday February 01, 2020 @05:31AM (#22209803)
C# has a great type system, but everything has ToString() and sometimes that doesn't output something sensible, and gets implicitly converted, leading to garbage.

Still much better than working in C or some other weakly typed languages.

Re:TypeScript’s quirks: How inconsistencies make the languag... by paavohtl on Saturday February 01, 2020 @05:01AM (#22209713)
As a long time TypeScript user, I do think this is a design mistake with the language. For example, it breaks instanceof checks.

However:

- The language primarily uses structural typing. If two classes are compatible, it's not completely unreasonable to expect them to also behave in a structural way (though I would prefer them not to).

- Adding a private field to a class makes it work as a nominal type (https://michalzalecki.com/nominal-typing-in-typescript/#appr...). It feels a bit hacky and it's not very well documented, but you could argue that until a class has some private state you can't publicly access, there's no reason to prevent you from declaring a compatible class.

- From my experience idiomatic TypeScript rarely uses classes, the primary exception being React components. In teams I've been a part of we've always written TypeScript (and JavaScript) like an (impure) functional language, taking full advantage of ADTs, simple structurally typed data and more-or-less pure functions.

Re:TypeScript’s quirks: How inconsistencies make the languag... by The_rationalist on Saturday February 01, 2020 @08:44AM (#22210458)
taking full advantage of ADTs What? There is no clean way to switch on the types of an ADT on typescript, I believe.
Re:TypeScript’s quirks: How inconsistencies make the languag... by alexcole on Saturday February 01, 2020 @08:43PM (#22214584)
Well discriminated unions are TypeScript's implementation of ADTs (but whether they are "clean" is could be debated)
Re:TypeScript’s quirks: How inconsistencies make the languag... by meheleventyone on Saturday February 01, 2020 @03:55AM (#22209525)
The problem is less that the syntax exists and more that people are used to nominal typing so get confused with edge cases where structural typing departs from it. The type checker isn’t breaking any promises it made it’s just slightly different from people’s mental model of how types should work from experience of other languages.

It’s just a different kettle of fish to learn.

Re:TypeScript’s quirks: How inconsistencies make the languag... by DonHopkins on Saturday February 01, 2020 @07:07AM (#22210081)
CatDog typing sure looks, walks, and quacks a lot like Duck typing.

https://en.wikipedia.org/wiki/CatDog

https://en.wikipedia.org/wiki/Duck_typing

Re:TypeScript’s quirks: How inconsistencies make the languag... by redmorphium on Saturday February 01, 2020 @07:29AM (#22210165)
From your second link:

https://en.wikipedia.org/wiki/Duck_typing#Structural_type_sy...

> Duck typing is similar to, but distinct from structural typing. Structural typing is a static typing system that determines type compatibility and equivalence by a type's structure, whereas duck typing is dynamic and determines type compatibility by only that part of a type's structure that is accessed during run time.

Re:TypeScript’s quirks: How inconsistencies make the languag... by kazinator on Tuesday February 04, 2020 @12:21AM (#22232662)
That looks like ooks like "original research". It's obvious that what is described as dynamic-only duck typing could be statically checked. So that is to say, a given expression foo.bar in the program could be statically checked to make sure that all possible values that foo takes on have property bar. If three classes A, B, C in the program have property foo, then this means verifying that foo is A | B | C. Thus, "static duck typing".
Re:TypeScript’s quirks: How inconsistencies make the languag... by greenshackle2 on Saturday February 01, 2020 @12:25PM (#22211689)
Kind of but not really. If you ask a "duck" to quack, duck typing is satisfied with any object that implements the quack method.

With structural typing, the type system will check that the "duck" not only quacks but also looks like and walks like a duck, before it is allowed to be asked to quack.

EDIT: of course with small enough interfaces you can get structural typing pretty close to duck typing, if you have interfaces "QuacksLikeDuck", "WalksLikeDuck", "LooksLikeDuck", etc. instead of one big "Duck" interface.

Re:TypeScript’s quirks: How inconsistencies make the languag... by dtech on Saturday February 01, 2020 @05:11AM (#22209747)
> If you can pass a Cat to a Dog function, where is the better checking?

If you have compatible method, fields and types, in a duck-typed ecosystem like Javascript it is a major boon that it is possible to interchange them, because it happens all the time in the ecosystem.

The standard way to do enforce exactly the right interface in typescript if you need to is to add a `type: "cat" | "dog"` field to your Animal interface and have the Cat interface have `type: "cat"`. If works well and is very similar to a JVM Class object or .NET Type object.

Structural typing, literal types and dependant types are major blessings to have available sometimes, and I'd really like languages to adopt some of Typescripts power and simplicity in this. So far I've only seen Julia have some of it, although Scala 3 also introduces some bits.

Re:TypeScript’s quirks: How inconsistencies make the languag... by kazinator on Monday February 03, 2020 @06:22PM (#22230487)
What is a boon is that I can write code that accesses obj.breed and have it work with any object that has a breed property.

That has some downsides; it can be abused to create a ball of mud.

However, a middle-of-the-road type check which insists that an object must have all of the properties of Dog, even ones you're not using, isn't very useful. It kills the above dynamism, and yet allows abuses to sneak through.

You will not find that cats are being passed to Dog functions until you try to maintain Dog. And then you will discover that, oops, everything you add to Dog has to be replicated in Cat.

Basically, a typecheck which says that an object coming in has to have all the properties of Dog might as well just be a subclass check. The smart way to ensure that a non-Dog class has all the properties of Dog is inheritance.

A properly done static version of this structural type check would validate that the object being passed to the function doesn't have all the properties of a Dog, but that it has all the properties which just that function requires (including transitively: through any functions it calls).

Re:TypeScript’s quirks: How inconsistencies make the languag... by blobs on Saturday February 01, 2020 @05:36AM (#22209822)
Whatever words you use, it simply conflicts with basic JS and is a serious flaw.

  const cat = new Cat();
  if (cat instanceof Dog) console.log('this should never be possible!');

What is this strange protective behavior towards TS, can we stick to logic please?
Re:TypeScript’s quirks: How inconsistencies make the languag... by redmorphium on Saturday February 01, 2020 @06:25AM (#22209968)
instanceof checks the prototype chain, which is a different concept from type. Prototype chains are dynamic and exist at runtime, while Typescript types are a static concept.
Re:TypeScript’s quirks: How inconsistencies make the languag... by mirekrusin on Saturday February 01, 2020 @07:16AM (#22210122)
Nominal types for classes feels like a better decision in flow, no need to mangle with phantom private props which is not the place you want to make this decision (when you call there could be this decision made but I can’t think for use case, making this decision at definition is too rigid and makes less sense).
Re:TypeScript’s quirks: How inconsistencies make the languag... by cryptica on Saturday February 01, 2020 @06:22AM (#22209955)
I still don't see the value added by TypeScript. My JavaScript tests catch typoed property names every time. I can't remember the last time I merged code with a typo in a property name. IMO, if you typoed a property name and your tests didn't catch it, it means that either your tests are poorly written or your object didn't need that property to begin with.
Re:TypeScript’s quirks: How inconsistencies make the languag... by redmorphium on Saturday February 01, 2020 @07:25AM (#22210158)
Some Typescript value added:

- Living documentation: types are a clear description of how your code and its data are laid out, and this structure is kept always up-to-date with the code, regardless of future changes. If the "documentation" (the typing) is wrong, the compiler will complain.

- Better tooling: autocomplete, more robust auto-refactoring

- Elimination of an entire class of bugs. This class may include: 1. `Cannot read property 'foo' of undefined` 2. forgeting a case in a switch statement 3. `'foo' is not a function` 4. in general, your code receiving data that isn't laid out in a way you expected

(Property typos is one within this class of bugs, but it is not all of it)

Yes tests catch these bugs as well. But tests are also manually written. And often not written at all. A compiler makes these (mundane) sanity checks automatic and mandatory.

---

Typescript's slogan is "JavaScript that scales" because static typing improves: dev documentation (via types living inside the code) and dev tooling (refactoring and autocomplete), both of which help immensely as a project grows in age (devs become forgetful), team size (new developers get lost), and convolutedness (e.g. tech debt).

Re:TypeScript’s quirks: How inconsistencies make the languag... by kjtekn on Saturday February 01, 2020 @07:43AM (#22210211)
Lets be honest here, these reasons are really weak. Living documentation - TypeScript is less readable. There is more stuff you have to read. Stuff that isn't even relevant. I see a "cars" variable. Oh no, I don't know what type it is, I am going to have a panic attack. Don't worry that cars.map((c) => c.model); is the next line or whatever. What type is it, I must know!

auto-refactoring.. yeah we all trust that. Until you come to the boundaries where all the types don't exist, like from the client to the server, to the database via its message system, etc. All the stuff coming in and out of your code is untyped.

Autocomplete works without typescript, even if it uses "the typescript engine". The types aren't needed.

Eliminates an entire class of bugs that nobody has ever had a problem with.

Re:TypeScript’s quirks: How inconsistencies make the languag... by JoeyJoJoJr on Saturday February 01, 2020 @05:04PM (#22213560)
I get the impression you either don’t have much experience with Typescript or haven’t fully grokked it’s workflow, and have prematurely made up your mind. Your autocomplete comment for instance shows you aren’t aware of the extent to which Typescript vastly improves autocomplete.

Regarding typing at the boundaries, this is precisely where typescript shines. The types exist whether they are documented explicitly in your code (in the form of interfaces, types, protocols, etc), or not. This is where the documentation aspect come in to play - it is far easier to read a type definition than having to chase up API documentation, mentally parse tests, or console logging out api responses, to understand your boundary. Your refactoring argument is a strawman, because you wouldn’t just go and refactor names of things at the boundaries of your code in typescript, or any other language, without understanding the API spec. What typescript gives you is precisely the ability to refactor at the boundary when the spec changes and be much more confident that your changes aren’t going to break a whole bunch of thing, especially when it comes to the “class of bugs” that literally every JavaScript developer has dealt with, whether you are aware of them or not.

Re:TypeScript’s quirks: How inconsistencies make the languag... by eatonphil on Saturday February 01, 2020 @09:19AM (#22210606)
> All the stuff coming in and out of your code is untyped.

Until you automate building TypeScript definitions from your external code. We do this to varying degrees and are always trying to improve.

Re:TypeScript’s quirks: How inconsistencies make the languag... by vhakulinen on Saturday February 01, 2020 @10:02AM (#22210808)
> TypeScript is less readable.

What makes you say so? I find it more readable than javascript.

Re:TypeScript’s quirks: How inconsistencies make the languag... by nicoburns on Saturday February 01, 2020 @06:25AM (#22209967)
Type systems can be thought of as low-cost (in terms of dev time) declarative tests. Which should leave you with less to test in your actual tests. They also give much quicker feedback than tests.
Re:TypeScript’s quirks: How inconsistencies make the languag... by cryptica on Saturday February 01, 2020 @07:41AM (#22210204)
Is TypeScript low-cost? Most TS projects I've worked on had at least a 10 to 30 seconds build waiting time per iteration. This means that every time I make a change and run the tests, I need to wait 10 to 30 seconds.

With my iterative test-driven approach, I probably iterate about once every minute on average (also, my development iteration time gets faster as I become more experienced in the project). So 30 seconds represents 50% of my total development time. Meaning that I could have written 50% more tests or 50% more features in the same amount of time. And that's not even accounting for my loss of focus incurred as a result of waiting 30 seconds to see the result of my code change. By the time I see the result, the concept in my mind is not as fresh as it was 30 seconds earlier.

Re:TypeScript’s quirks: How inconsistencies make the languag... by Fannon on Sunday February 02, 2020 @03:30AM (#22215878)
Are you aware of tsc options like --watch and --incremental ?

Combined with other live-reloading tools like nodemon or jest --watch you can have almost the same speed of your development-test-run-debug loops as in plain JS. But you do gain an additional instant feedback channel from the compiler.

Re:TypeScript’s quirks: How inconsistencies make the languag... by kjtekn on Saturday February 01, 2020 @07:45AM (#22210215)
No longer enjoying programming is a cost nobody can afford to pay. When I read the long list of c#, I mean typescript documentation, it gives me PTSD from c# and java, which people used to hate here, but now suddenly like and let me tell you it has nothing to do with microsoft social engineering.
Re:TypeScript’s quirks: How inconsistencies make the languag... by BorisTheBrave on Saturday February 01, 2020 @09:26AM (#22210638)
Devs should enjoy writing trivial tests? Heaven forbid businesses might care how quickly something is delivered?

Let us know when you are willing join the rest of us in the real world.

Re:TypeScript’s quirks: How inconsistencies make the languag... by TomMarius on Saturday February 01, 2020 @02:43PM (#22212736)
I also used to think TS is like C#. Huge mistake. Try to approach it from a functional angle. The TS compiler code does not use the class keyword.
Re:TypeScript’s quirks: How inconsistencies make the languag... by vhakulinen on Saturday February 01, 2020 @10:06AM (#22210840)
> My JavaScript tests catch typoed property names every time.

My typescript compiler catches typoed property names every time.

> I can't remember the last time I merged code with a typo in a property name.

I can't remember the last time my newly written code made it into the runtime/browser with a typo in a property name.

> ...if you typoed a property name and your tests didn't catch it, it means that either your tests are poorly written or your object didn't need that property to begin with.

The types are much more than just property names.

Re:TypeScript’s quirks: How inconsistencies make the languag... by lscharen on Saturday February 01, 2020 @09:43AM (#22210722)
If TypeScript is used against bog-standard JS code, I can definitely appreciate your point.

For me, TypeScript really started to shine once I started taking advantage its generic support, higher-level utility types like Pick<> and Optional<> (and really anything involving keyof), and creating static type checks via the unknown and never types.

This is especially effective when working on legacy JS code bases where unit tests and other good engineering principles were not used well, or at all.

Re:TypeScript’s quirks: How inconsistencies make the languag... by DonHopkins on Saturday February 01, 2020 @07:11AM (#22210099)
Do your JavaScript tests inform your IDE how to do code highlighting and completion and refactoring?
Re:TypeScript’s quirks: How inconsistencies make the languag... by cryptica on Saturday February 01, 2020 @07:32AM (#22210180)
My JavaScript integration and unit tests do something better; they tell me exactly what features I broke as a result of my refactoring and let me fix things in the best way possible without regard for the previous structure of the code (which may no longer be relevant anyway; there is usually a good reason why we do refactorings in the first place! It's rarely just about renaming things).

I have many stories on the subject but most recently I did a significant refactoring for a JavaScript project (a popular open source library I created) to move from callbacks to async/await and was able to re-use pretty much all of the existing integration test logic with only aesthetic changes (to account for the new async/await API).

When I finished the refactoring, I had modified at least 70% of the entire source code of the project and I took it as an opportunity to make significant structural changes to my code to align with the new async/await flow in the most optimal way possible. This kind of big refactoring would have made code highlighting completely redundant and would have prevented me from looking at the problem with a fresh mind and taking into account the new features offered by async/await. It was a very successful refactoring; no new issues were uncovered after the point that I managed to get all the original tests passing again and the code was a lot simpler than before.

I think TS has a way of locking down old structures in a way that make it sub-optimal in the long run. Feature-oriented tests are by far the best way to ensure that product quality is maintained after a refactoring IMO.

Re:TypeScript’s quirks: How inconsistencies make the languag... by the_gipsy on Saturday February 01, 2020 @01:01PM (#22211993)
I have the exact opposite opinion on "code lockdown". I believe that unit and integration tests heavily lock down code, so much as being mere checksums.

In a project with >90% coverage, I would find refactors dreadful. After any substantial change beyond adding stuff, there were always a myriad of tests failing. Not hard to fix, but simply tedious and dreadful.

On the other hand, I have an Elm project with no unit test, only some e2e tests. I can do huge transversal changes, and I don't find ot tedious at all. It gave me back the fun in programming. The Elm project is a game, so there should me an order of magnitude more bugs, but the opposite was the case.

Re:TypeScript’s quirks: How inconsistencies make the languag... by cryptica on Sunday February 02, 2020 @04:57AM (#22216150)
Well designed tests lock down features not code. That's why I mostly write integration tests.

I write unit tests once the project is stable and usually only for parts of the logic that are either very complicated or operationally critical. I try to avoid implementing 'very complicated' modules as much as possible.

Re:TypeScript’s quirks: How inconsistencies make the languag... by the_gipsy on Monday February 03, 2020 @05:43PM (#22230165)
Do you mean e2e tests? Because those are the only ones that test features. Integration tests are the biggest offenders of "code lockdown". They don't really test features, yet they have to observe too many implementation details.

Unit tests can't really lock down code, or then we shouldn't call those "unit" anymore.

Re:TypeScript’s quirks: How inconsistencies make the languag... by blobs on Saturday February 01, 2020 @05:14AM (#22209758)
> TypeScript crew have managed to build something that can get traction where other efforts have not.

You mean Microsoft managed to get traction? It seems most TS proponents don't realize TS is a success because they fell for smart marketing and serious money behind the project, not because it's a better language than 'other efforts' like for example Purescript or Dart.

But every comment I make against TS seems futile. TS proponents defend their little language very fiercely regardless of all the flaws it has. It's almost worth a study how Microsoft managed to do that. Overall a real pity, because there are so many better options and ideas for those who want static typing. TS is actually the worse choice IMAO.

Re:TypeScript’s quirks: How inconsistencies make the languag... by DonHopkins on Saturday February 01, 2020 @07:16AM (#22210121)
>It's almost worth a study how Microsoft managed to do that.

It's almost as if Microsoft learned the techniques of linguistic evangelism from Sun when they studied the ideas behind Java to design C#, but they left out the anti-linguistic-miscegenation Java-supremacist ideals of "100% Pure Java [TM]" when they made it easy to integrate other mongrel languages with COM and P/Invoke.

https://news.ycombinator.com/item?id=19571635

Re:TypeScript’s quirks: How inconsistencies make the languag... by TomMarius on Saturday February 01, 2020 @06:12AM (#22209927)
They did it by solving a great pain of a very large amount of people. Not many of these people would have been able to use Dart or PureScript.
Re:TypeScript’s quirks: How inconsistencies make the languag... by tigershark on Sunday February 02, 2020 @01:44AM (#22215548)
Typescript unlike Dart, Purescript, Fable and BuckleScript is a superset of JavaScript so you don’t have to change anything in your existing JavaScript project to start using Typescript. Also JavaScript interop is a breeze and a huge percentage of the libraries have already typescript binding and it’s a huge advantage compared to using the aforementioned languages.