> trivial problem
Type checking is quite non-trivial, especially as the logic and types get more advanced (conditional types, index types, mapped types, etc etc). Not just “typos”.
float multiply(float a, float b) { return a * b; }
You can’t add doubles with this code because it’s coupled to the float type. Summing a for b times has no logical coupling to floats or doubles just as floats or doubles have no logical coupling to either implementation of addition - both types are added by the same operations. You can swap the types or the algorithm.Before you reach for the polymorphism or further pollute the universe of types consider that it costs less lines of code to erase types here.
What errors would preserving types help with here? What has more utility, less lines of code spent for the same outcomes or an implementation that exists further along the spectrum of typing in the “at compile time” direction? - I don’t believe that question can be answered but in practice i find less lines of code correlates more strongly with outcomes i care about than the degree of typing applied.
Pretty simple, it helps when you do a refactoring that changes the type of the value passed somewhere from number to number[] and the compiler instantly tells you that that’s illegal.
I did something similar just the other day when I had a shared config file read by both TS scripts and Python scripts and I needed to change the format to support a new feature. On the ts side I updated the typedef and the compiler pointed out to me every area that needed updating, on the Python side I had to spend a good chunk of time manually going through the script to figure out what needed updating.
Typing isn't a strong enough tool to combat that class of problem; you can fix the type signatures while introducing a semantic break. You need tests and if you have tests, what does typing bring? Keep your tests fast, measure and maintain a speed of >250 tests per second and remember to test behaviour not implementation - you won't go far wrong.
IDEs have been performing refactoring changes on our behalf in dynamic languages for years at this point. Don't manually edit when we've never had such powerful tooling available to us
* https://www.jetbrains.com/help/pycharm/product-refactoring-tutorial.html
* https://www.jetbrains.com/help/pycharm/structural-search-and-replace.html
Even concepts that i'd say are strictly the domain of static typying, like automatically pruning dead code behind retired feature flags, make headway today: https://github.com/jendrikseipp/vultureTyping has a time and a place, that is without a doubt but the world is better viewed without the static typing lens permanently affixed in place, your efficacy will increase.
I’d never choose to have myself do more work if it’s not needed and the computer can do it.
Those automated refactorings would Not have helped in the situation I mentioned above.
It’s whether it continues to work tomorrow after you’ve added or removed a behaviour. Tests are the secret sauce that keep the cost of change low.
Refactoring (a commit with zero changes to test code) is the other key pillar of long term codebase health.
How do the benefits you get, relate to the difficulty of problems you’re solving when programming?
Eg if the cost of types is increased coupling of code but the trade off benefit is it makes fixing typos easy then that’s a bad trade. You’ve made a hard problem more brittle in exchange for making a trivial problem even easier.