I myself have found this to not be true, and I have found the same in reading / talking to others. However, if you have found a resource that has data on the contrary, I would find it very interesting to read.
https://medium.com/javascript-scene/the-shocking-secret-abou...
That is, past the first time I run it. I've been known to pass something an x when it wanted a y, but that's a "fail early, fail loud" bug and not an actual problem.
Also you have no guarantee that what you think the types should be is actually consistent.
In fact, I'd say that most of the time, a good statically typed language does the opposite of get in your way. It helps you w/ refactoring tools, better intellisense and editor help, self-documentation, etc. The older a codebase gets, the more helpful a static type system is.
That said, there are statically typed languages which produce a ton of boilerplate (Java used to, at least), and there are those that don't (F# comes to mind).
The only dynamically typed language I've used where I didn't regularly miss static typing is Clojure. (Elixir may fit the bill, but the jury's still out on that.)
Let me add a radical point: static typing is often thrown out anyway, when you encode your data as strings, serialize/marshal it, create polymorphic lists and hierarchical data structures, etc etc
Meanwhile, disciplined use of python is perfectly easy to get right: - use pylint - be ruthlessly consistent in naming classes, methods and variables (which pylint helps btw,) - for large projects, consider mypy etc
I program C# a lot, I never fight the type system. It helps me. It tells me while coding that something is wrong. In Python I'll catch this as well...eventually, when I run the code. A type error in C# would be a runtime error in Python. That's very inconvenient.
The static types are also documentation showing intent. It's hard to read old dynamically typed code bases, because I have to do the type processing in my head to understand what is what. Much simpler if I have nicely defined interfaces.
Besides, tests cannot find all the bugs a good static type system can find, and vice versa. Tests, even at 100% coverage, are not a complete substitute.
There are so many tests you can throw away, so many corner cases you don't need to test anymore. (I'm talking about tests that you can't even write down without getting a compiler error.) Not to mention the assertions within your functions that aren't needed anymore.
And those little type annotations are so much simpler and easier to write down than corresponding tests.
If you really head for 100% testing, not just code coverage, but also all corner cases, you will love the modern static type systems. (However, you should really use an ML type system, because doing the same with Java or C++ is cumbersome and not much fun.)
[1] I did so for my mathematics diploma thesis, starting implementing my formalism in Python, having lots of trouble when refactoring, then moving all code to OCaml and then being able to refactor the code alongside the developing formalism in the thesis.
Meh, test are great in so far as they can help you not break things if you upgrade the framework, or langauge in the future. But other than that I have to agree with Kent Beck's sentiment of "I get paid for code that works, not for tests".
https://istacee.wordpress.com/2013/09/18/kent-beck-i-get-pai...
If I had started out trying to learn Django using TDD as in this tutorial:
http://chimera.labs.oreilly.com/books/1234000000754/index.ht...
I never would have learned Django. I would have given up with the ridiculous slow progress of results and functionality.
The idea that you could somehow replace the utility of static type checking with a suite of human written tests is laughable. Static typing systems allow you to prove facts about your code which make reasoning about correctness much easier than with dynamic type systems which practically disallow this (unless gradual typing is allowed in your language).