Given that you have a good system for monitoring errors in production and a low friction deploy process so you can quickly and easily fix errors when you discover them, I feel these kinds of errors are honestly not worth guarding against in most contexts outside of those where getting everything perfectly right the first time is a hard requirement (health, fintech, other safety-critical industries, etc).
Of course, most companies lack either or both of these ( a good system for monitoring errors in production and a low friction deploy process), so they use static typing as a clutch to try to reduce the chance of errors making it into prod simply because they know they'd be slow to fix/detect those errors. That's a poor reason to choose static typing IMO, but I think that's by far the most common reason.
Whether or not that delta is worthwhile compared to a dynamically typed codebase with a well-optimized deployment/error detection system is not always clear however. Especially considering the costs of a static type system in limiting expressiveness compared to dynamic code and the mental overhead required when building abstractions that require layers upon layers of generics and higher order types to fully specify statically (library authors probably feel this pain the most).
I'd encourage you to keep your mind open to it's potential benefits as I've felt it has been a truly transformative experience that I'd like others to share.
It's also common to encounter errors in production that are difficult to reproduce in the development environment, this is especially true of data-type errors in dynamic languages where some unusual edge case creates a strange data structure that would simply be impossible with static types.
There's also a chance that the developer fixing the code didn't actually fix it and instead only introduced enough guard logic to handle that one specific case based on their best guess regarding the shape of data that can come through, thus redeploying with a 30% error rate instead of a 60% one, repeating the cycle of attrition testing against the production environment until the error rate is "noise" but maybe not completely fixed.
Now I avoid using regular JavaScript.
I'm impressed how many bugs it prevents, and it prevents them early.
Refactoring in TypeScript is literally magnitudes easier and quicker.
Such arrogance.. ..and unfortunately so typical for TS proponents..
Sure but unless you have coverage of all error cases, it’s nice to have that check at build time vs some untested corner case in production.
> Given that you have a good system for monitoring errors in production ...
Runtime errors are a totally different beast.
> ... and a low friction deploy process so you can quickly and easily fix errors when you discover them, I feel these kinds of errors are honestly not worth guarding against in most contexts outside of those where getting everything perfectly right the first time is a hard requirement (health, fintech, other safety-critical industries, etc). Of course, most companies lack either or both of these ( a good system for monitoring errors in production and a low friction deploy process), so they use static typing as a clutch to try to reduce the chance of errors making it into prod simply because they know they'd be slow to fix/detect those errors. That's a poor reason to choose static typing IMO, but I think that's by far the most common reason.
Fixing things earlier is cost effective regardless of your deploy speed. Sure it’s worth more the longer the cycle, but not having to run unit tests because the compiler knows “foo” is not “fo0” saves time as well.
I'm not saying detecting errors earlier through static typing has no value of course. Just that there is a spectrum of value a team can derive from static typing that scales based on the length of their deploy and error detection cycle, and at the lower ends of that scale it's not always clear that static typing provides enough of value to justify its costs.
And that if a team doesn't already have them, investing to minimize the deployment and error detection cycle is often much more valuable than investing in static typing because it's an effective tool for both dealing with runtime errors as well as errors that could have been statically determined.
For a small team full of talented engineers (e.g. a startup) it's not unreasonable at all to just... not make typing errors. I've put 5+ large apps into production in the last decade and could probably count on one hand the number of times I've really struggled with something type related.
There's certain anti-patterns that make up the majority of type-related problems in JS. Things like inconsistently mix 'n matching falsey types, adding or removing properties from objects in unpredictable ways, or leaking stringified numbers and bools everywhere.
Other classes of type problems can be solved in dynamic languages by structuring code in more self-documenting ways and properly augmenting any remaining ambiguity with comments.
If your team is naturally coding in a way that respects the dynamic typing of the language then your benefits from TS are going to be much more marginal, and that needs to be taken into account when comparing the costs and benefits of it.
My guess is that we'll see a harder split in the JS community in the next few years. Most people are going to drift towards only taking on TS or JS roles in much the same way most JS programmers wouldn't take a lisp or C# job at the moment.
This is one of the advantages of typescript over a language like clojurescript.
However I think it’s important to have used both for a while so you can make a good decision what you prefer.
Even though I seem to be in the “intelligent” camp by your definition.
Exactly, I always found static typing to be annoying clutter and Python seemed to work even at scale. I removed the few type hints the codebase had.
Then I had to spend a year in C# professionally. At the end, I was fine with both, no preference. Then I jumped back into our Python and only then realized the utility of typing - it felt chaotic, my (IntelliJ) IDE was no longer helping me and every time I had Prod type related bug, it feeling dumb.
Ended up type hinting the critical parts of the Python.
I think of it as "I don't care what the type is, but I also shouldn't be able to do anything with it"
All things being equal I prefer something like Haskell because it is very clean and expressive. But I hate excessive types when you are dealing with generics 3 level deep or when you have these funky type signatures dealing with monad transformers. It's just too many layers of abstraction that takes you away from the actual data / parameters.
When I'm writing something small I find typing slows me down. But when writing something bigger, working in a team, or working on a codebase for a longer period of time the typing acts as documentation. Typing something and having Intellisense tell you what is in a class is extremely helpful. Otherwise you have to jump to the file or look through documentation.
For me it's less about the errors it catches and more about the time saving of not having to read through code that I am calling in order to understand what I need to pass to it.
In general. strong typing is great when you are working with other people's code and 3rd party libraries, but excessive overhead when you just want to experiment and crank out something small.
For static-lovers, the idea of "just fix it if it breaks in production" is horrible. For dynamic-lovers, the idea of "spend time on work which doesn't get you closer to solving the problem" is essentially wasted effort. (Static-types are 'meta' code; the equivalent program works just as well without the types declared).
I've heard a good strategy is that the first-iteration should be dynamic (this gets the problem solved quickly), and static typing is good for further iterations (static-typing is better at conserving what's there).
This is a huge problem with front-end. Too many people who don't know what they don't know, and think their use case is the only one.
With dynamic typing, you don't get the immediate feedback of breaks when making frequent changes. You don't get the safety of automatic refactoring. You don't get auto-complete and easy of discovery of APIs.
I really don't understand the idea behind dynamic typing being better for prototyping unless that "prototype" is only a few lines long.