HACKER Q&A
📣 rmnull

How do you get over typed languages?


Hi HN,

I had to put some prototype together in python and I just find it hard to work with it now. Python is something I used to regularly write and then ship code asap, now all the various scenarios where it can fail just runs in my head and I end up implementing multiple strict checks in places and even then I'm just bothered about future changes breaking these things. I'm skeptical and I have to go and write a lot of tests so that thins don't break and some of them are just silly tests like checking value is in the correct domain. I don't mean to particularly bash on python. Since its not Python's fault. Same goes for JS, I can no longer write plain JS now. I just reach for TS. This is partly due to the fact that I was working on typed code(TS[0] and Java[1]) for last few months. And some of the code in there required correctness guarantees, and it was just easier to reach out for typed language since I get many of the checks for free. However after going there, I find it hard to come back to writing dynamic languages now. Once I've realized that typed languages allow me to restrict my domain and the guarantee that this function can just bother about this restricted domain. I worry free write my code and the tests. I get some sense of confidence in what I'm building. This obsession with staticly typed language has been making me unproductive. And I can't find myself going back to it, even for something like scheme which I love so much I just can't find myself going back to it.

# Footnotes [^0]: Strongly typed TS, no any, and for dynamic values, used to use unknown parse into a known type and then continue with that. Ye there are some downsides here too, for e.g: I was not able to maintain few guarantees here like : if I take X = XS[0], there is no way for typescript to guarantee that X is a value is that is guaranteed to be contained in XS.

[^1]: Yea, Java type system is not the best, I have to use hacks like inheritance to make somethings work, anyway its better than no type system, especially I hate that java allows null which is a major source of annoyance for me and i keep wrapping values in that Optional monad.

==========

TLDR: How do you manage to code in dynamic languages after being exposed to static typing.


  👤 gibbitz Accepted Answer ✓
Dynamic languages require different approaches to problems than statically typed languages. Generally I design my APIs differently in dynamically typed languages. Reducing the opportunity to pass bad values, not using more than two function parameters and not overloading. Using scoped functions that are closed to end users puts you in control of the values passed in. Not using OOP if it isn't natively supported in the interpreter, etc. JavaScript makes simple checks easy by evaluating 0s, empty strings and undefined as falsy. Over tightening these checks increases development time and maintenance overhead with little actual additional "safety". It's better to take a minimal approach and add checks when errors occur than to try to predict errors that never occur with a comprehensive aproach. In this way adding types to dynamic languages is just premature optimization.

Another important factor here is the implementer's ability to troubleshoot. If you don't know how to detect and find a mistyped variable you need to accept that you don't know the language and ask someone who better knows how to run and troubleshoot applications to help you find it. Dynamically typed language interpreters/compilers provide feedback that is sometimes opaque but generally offer clues if you know where to look. It's not the same experience as having a compiler in your IDE that can show you the potential error as you enter it, but dogs are not cats either.


👤 zahlman
The most important thing to realize is that, if you can no longer feel comfortable with shipping code "that can fail in various scenarios" then you would need the tests anyway. TypeScript and Java are not Coq, and you probably wouldn't enjoy using a properly rigorous language like that anyway (and the kinds of programs that can actually be "statically proven correct" are generally not very capable). Type checking doesn't make e.g. the halting problem go away; you are only verifying that types are compatible and not that the code actually does what it's supposed to do.

Anyway, when you write code in a dynamically typed language, you do work in a restricted domain - just implicitly. You expect the input to provide a particular interface, and if it doesn't, there will be some kind of runtime exception. Oh well. You use exceptions for runtime debugging, not just to detect user error. Yes, this does require a different sort of discipline.

But there is no accounting for taste. The language you describe are not only statically typed, but manifestly typed - i.e., you need to explicitly specify types within the code. Some people like the visual reminder; others loathe the extra typing (er, keypresses). Of course there are also statically typed languages that infer typing from use patterns, such as the Haskell family.

> I was not able to maintain few guarantees here like : if I take X = XS[0], there is no way for typescript to guarantee that X is a value is that is guaranteed to be contained in XS.

Well, yes; membership in a container is not type information. It can't be, not for mutable containers anyway. After all, the contents are determined at runtime.


👤 syndicatedjelly
I have this pet theory that a well-written dynamically-typed program will have fewer bugs than the typical statically-typed program.

Static typing doesn't reduce bugs. It just changes when they appear, from runtime to compile time. Further more, types are largely about communicating information about how a client should use a piece of code. A compiler for a statically-typed language just happens to help automate this exchange of information and reduce the likelihood that the code is used incorrectly.

It's kinda similar to precision vs accuracy; to be precise means to throw a bunch of darts at the same spot on a dartboard, and to be accurate means to actually hit the bullseye. A lot of typed programs are precise, but end up solving the wrong problem.


👤 greentea23
By adding types back in :) mypy and pyright are fantastic. It's very much productive to annotate types. Debugging or extending untyped code is quite unproductive, not just for future you but for anyone else, amplifying the inefficiency.