6 ms·
> bugs are usually in the flow itself and have nothing to do with wrong types I'm not sure what you mean by "in the flow itself" exactly, but just yesterday a
by Vinnl 6y ago
> bugs are usually in the flow itself and have nothing to do with wrong types
I'm not sure what you mean by "in the flow itself" exactly, but just yesterday a teammate of mine was using one of our libraries in a small project without TS. They first called getThing(), which might return null, and then passed the result to doSomethingWithThing(), which did not expect a null. That sounds like a "flow" problem to me, and TypeScript literally would've warned them of it.
(Since this particular combination of functions is likely to be common, we added a runtime check for people who aren't using TypeScript now.)
> Most devs using it have never seen vanilla js and are more java minded that prototype minded.
I think you might be underestimating the number of people who strongly dislike Java's type system but very much appreciate TypeScript. They're very different, and hence it's very much possible to like the latter for reasons that do not apply to the former, or to dislike the former for reasons that do not apply to the latter.
- CraigJPerry 6y ago>> They first called getThing(), which might return null, and then passed the result to doSomethingWithThing(), which did not expect a null When i think of a flow issue it's more things like "i forgot to check if the user was authorised to perform doSoemthingWithThing()"
- mlnj 6y agoAnd with TypeScript I get notified that I forgot something and it shows me exactly where.
- CraigJPerry 6y agoCan types solve that problem? ... // if(isAuthorised(user)) { doSomethingWithThing(thing); // } ... How would typing detect the missing authorisation check in the program flow? Surely this is a case where testing is the correct tool to use?
- deleted 6y ago[deleted]
- egeozcan 6y agoWhen User is a type of: Guest | AuthenticatedUser and isAuthorised is a type guard like: function isAuthorised(user: User): user is AuthenticatedUser { return user.isLoggedIn /* or whatever */} as long as doSomethingWithThing accepts just AuthenticatedUser, yes it can be caught. You can also use discriminated unions with implicit type refining from TS without type guards.
- mlnj 6y agoAnd beyond the isAuthenticated() / isAuthorized() call in the flow there only needs to be the use of AuthenticatedUser.
- CraigJPerry 6y agoWait doSomethingWithThing(thing) Doesn't know about user, why does it need to be polluted with the concept of an AuthenticatedUser type which it does nothing with?
- egeozcan 6y agoIf that action has a dependency to a user (an authenticated user or a user with a specific permission), it's a good practice to establish this dependency also in the code level. "doSomethingWithThing" probably does IO, and the changes need to be traced back somehow (e.g. a ModifiedBy column in a DB). You can solve this context problem through a DI container, or by direct parameter passing, but whatever you do, there will be a layer which can expose the requirements as types. I'm not a know-it-all who'll dictate how you need to structure your program on HN, so what I stated above is just me thinking out loud, but let's say it's up to the programmer to make everything safe-r with the tools available, be it runtime checks or the type system.
- filoeleven 6y agoI think GP may have meant to say that whatever code is _calling_ doSomethingWithThing() there should only accept AuthenticatedUser. It hoists your original check to the calling function’s signature. I agree with you that this doesn’t really solve the flow problem though: someone still has to decide that the function only receives AuthenticatedUser and not Guest. That’s not a net gain, it’s just shuffling responsibility around, and it could be a net loss if the calling function does “a bunch of identical things for any user type” and then “this one extra thing if user is authenticated.” But I’m not a Typescript user or a big fan of complex type systems either.
- hajile 6y agoThere's a correlation between lines of code in a file and bug count. Does the typing outweigh this? If all the time spent writing all those types was spent debugging, would TS win in actual development time? If you're writing good unit tests already, why are you running into so many type issues? If you already have to spend time writing tests, why spend more writing types? TS types aren't really documentation. For other devs to use your stuff, you need JS Docs to actually explain things. Why write all those types too? If I'm writing a quick and dirty project, it feels like TS types help a little, but if I'm following best practices on an important project, TS seems like pointless ceremony that slows things even more.
- Vinnl 6y agoI don't have numbers on that, though I think a sibling comment did refer to some. I do have my intuition though. (One day I'm going to keep track of the mistakes TS catchers early for me in a week.) So yes: I think the typing lowers the correlation between lines of code and bug count, and that that outweighs the bugs introduced by the additional lines. (It is similar in that regard to many unit tests, I'd say.) As for unit tests: it's not that I write unit tests first and add types later. The types are written as I code, and they allow me to not write some of the unit tests I'd written otherwise. The upside is that they're easier to write and easier to keep aligned with the code than unit tests. So yes, I still have to spend time writing tests, but less of it than without types, and I save more time than the writing of types costs me. > TS types aren't really documentation. For other devs to use your stuff, you need JS Docs to actually explain things. Why write all those types too? I don't understand what you mean by "write all those types too"? Yes, I still have to write documentation, but just iterating the types is not documentation?
- hajile 6y ago> I don't have numbers on that, though I think a sibling comment did refer to some. I've read that paper in the past and it doesn't actually answer most of the questions I asked above. It only says that X bug existed in some prior git commit. Maybe the dev caught that bug and fixed it before the PR with the commit was merged. Maybe it was caught in code review. Maybe it was theoretically possible within the function, but not within the actual program's use of that function. Maybe the time spent catching those bugs was less than the time it would take to add types. > they allow me to not write some of the unit tests I'd written otherwise A `typeof` assertion or similar is hardly more work and continues to function once the TS types have been stripped. If you expect to interact with the outside world, then you must test against unexpected types. If not, then good docs are still better (see below). Meanwhile, in every real-world TS project I've worked on, you wind up with tons of "template soup" where devs spend tons of time trying to find out which variant makes the type checker happy (or just giving up and slipping in an `any` type) > Yes, I still have to write documentation, but just iterating the types is not documentation? I have a function that takes a string and returns a boolean. What does it do? It's likely that I can pass it any string, but there's a strong possibility that the function can't handle any random string. Does that boolean mean it's a test, that something was successful, or something else? What about side effects? By the time you're done documenting this, when someone glances at the docs, they'll probably not worry very much about the types because they'll be obvious. Why write up a bunch of complex types when a simple, human-readable doc string does types and so much more?