Unlike other languages where if you update to the new version and get a whole bunch of build errors about methods not existing for a type or this function now returns a different type, you had to run an %80 of the way there migrator who's effects you weren't completely sure about and run your app through your unit test suite. Almost nobody has %100 unit test coverage to approximate what a build statically typed language compiler does, some functions 'worked' anyway due to duck typing and did behaviors that were different than what you were expecting and a bunch of methods returned a slightly different string type that gave more errors, only when you ran the code, each exception at a time.
While in a static language you can just run it, and you would of saw all the places where a function now returned a bytestring and deal with them all at once, properly. I've dealt with several breaking change migrations with the swift language, and although annoying, it was tractable and only took a day or two without worries about hidden gotchas.
Nowadays my minimum requirements for static types are:
- Nullable types (does this type container accept nil or not)
- Very basic generics for containers
- Typical static typing features
Bonus:
- Enums with variables (also known as ADTs)
The reason why I chose these features specifically is they give you a lot of benefit, but are not actually slow to compile and not complicated to implement for language maintainers when first writing a language. I hope golang has all of them one day.