I understand that many people say that with static typing if it compiles it works, but I remember using debuggers quite a lot.
I'd say that if one wants types there are plenty of languages to choose from. There is Crystal if one likes Ruby.
Contracts are interesting. I remember Eiffel and other languages. Those could be useful regardless of the kind of typing the language use.
BTW, invariants are another useful tool when designing some algorithms and were neglected recently.
Java is a pretty terrible language when it comes to static types. If you have a language that allows you to work with types in a succinct and expressive way, you end up with a powerful modelling tool that can help you reason about and design programs. The side-effect of this is to have far less runtime crashes (you know what cases to check for, like nullable data), great documentation for your future self and your fellow devs, and a greater liberty to do large scale refactors without worrying about breaking things.
Kotlin is an excellent example of such a language, and I'd highly encourage anyone, especially devs with a strong Java background, to try it out.
In contrast, contributing to an existing codebase in PHP or Rails is much harder. Nothing will stop you from sending the wrong arguments to a method, or adding members to classes that should not be modified, or even simply refactoring and forgetting to change all of the usages of the types and methods you modified.
Which really means there's a big difference between static types that everyone knows and uses, and those that someone invented for particular use. That difference seems more significant than the static/dynamic divide.
Many people's impressions of static languages are based on Java from 10 years ago. It's really quite different now.
I'm with you on the excess typing thing, but I still think types are useful just for tool integration. One day I hope that a popular language will emerge that presents an AST so that we can have non-type based refactoring browsers like Smalltalk's.
Most of my time is spent playing the game "which type is this?".
Yeah, one can write unit tests to play the role of the compiler's type checker, but in the enterprise unit tests are pretty low in the deliverables list, usually the bullet following documentation.
Unfortunately I feel like this is where types are least likely to be useful in Ruby and Python. Static typing means that you know the type of a value coming into your function, but you can achieve exactly the same thing by dynamically profiling the type, just-in-time specialising the function for it, and then on each call all you need to do is check that the type is what was expected. The check will probably be just one machine word comparison. So static typing saves you just one instruction!
However it would remove the time, memory and complexity needed for the profiling. I'm not sure that's really a big overhead though.
I work on implementing existing programming languages using new technology, and in some cases we basically discard static typing information for the purposes of optimisation, because we can work out better information for ourselves at runtime using profiling.