Having written extensively in several statically typed languages, it was still possible to send messages to nil and end up crashing, or just be lazy and not deal with every possible conditional when parsing incoming data from an API and end up crashing, etc. (I use these examples because these seem to be what people reference the most — perhaps you are referring to something else).
Like, it just does not happen (in my experience, to be fair), that someone is passing a Car into a method expecting a Flower. It's nice that the compiler would flag that for me, but it's just so rare in my experience.
Types don't just guard against catastrophically stupid errors like Cars instead of Flowers. You can use them proactively to tag and refine data, excising a considerable deal of logic from your code.
If you are dealing with priority lanes, all of the methods could be written to only accept Carpool types, even if a Carpool struct has the exact same fields as a Car. Then you only need to parse a Car to a Carpool once and never worry about validating the passenger count after that.
Static typing only seems like a verbose straightjacket in the context of verbose languages like Java and Go. In reality it can help you write way less code. I don't expect the world to switch to Haskell, but I am excited by the direction TS is heading. I think "parse don't validate" will become common wisdom eventually.
Also, the crash cases you mention could be avoided elegantly with Option types.
Amusing to hear Go described as verbose. Given that it was intended to not be verbose! Do you care to elaborate? To me, having done lots of Python, I find Go irritatingly lacking in batteries included, lack of classes stumps me, and Go seems certainly no more succinct than Python. I find Go seems possibly less verbose than C++, definitely better than Java ( that wouldn't be difficult ;) but perhaps harder to read. However, I've only dipped my toe in with Go, so possibly approaching it completely wrong and need to learn the Go mindset....
As the sibling comment alludes to, checking errors is a major pain and needlessly repetitive if you expect any exception in a chain of computations to be handled the same way.
I can't speak for Rust, but in Haskell you can just do something like
f >=> g >=> h
in the context of Either or whatever.
All of this has nothing to do with Go's specific typing discipline or syntax around it, of course. I was just commenting on how the most popular static languages probably aren't the prettiest or most reliable examples of the approach. Plus Go is far more likely to shit the bed at runtime in spite of its typing.
Yes this! I've worked so much with static typing and I always think this when people talk about all the bugs that it prevents. I do from time to time wonder why stuff isn't working while I'm building it in a dynamic language just to find that I have a typo somewhere and I might get annoyed but then I think about all the types I would have to write and maintain and I'm happy again. I'm convinced that most of the time there is not enough ROI to justify the added complexity and mental burden of adding something that does nothing for the problem you're trying to solve.
It also is a form of documentation. I love when someone doesn’t type code but then ends up adding the types in the doc string, why wouldn’t you just type it then?
Agree 100%. However... since nowadays we all do TDD (right? ;). I hope so! ). and write thorough unit tests, this should be less of an issue. I remember years ago when switching from the likes of C++ and Java, to Perl and Python. Indeed there were problems that occurred in these otherwise-nicer-to-use-dynamic-langs which would've been caught by a compiler, but that was before TDD being so standard.
> ... since nowadays we all do TDD (right? ;). I hope so! ).
Everything in moderation. TDD is good, but I've watched people write extensive tests before writing a line of code to test, and it often ends badly -- not too badly, they usually just needed to rewrite the tests once they figured out that they had the wrong API (oops, at least one example was a case for DOD, because the API was perfectly obvious from that lens) but sometimes that can trigger multiple refactors along the way. I've seen the same thing happen with documentation-first. I've seen top-down problems and bottom-up problems and code that ships before tests or docs were ever written/validated. In my not-even-remotely humble opinion, people need to be familiar with all the design patterns, and figure out which is best at project inception.
Having written extensively in several statically typed languages, it was still possible to send messages to nil and end up crashing, or just be lazy and not deal with every possible conditional when parsing incoming data from an API and end up crashing, etc. (I use these examples because these seem to be what people reference the most — perhaps you are referring to something else).
Like, it just does not happen (in my experience, to be fair), that someone is passing a Car into a method expecting a Flower. It's nice that the compiler would flag that for me, but it's just so rare in my experience.