The problem I find with static typing is that it so easily leads you over-specifying the requirements / constraints. In fact, it makes such a virtue out of that over-specification that many people would consider it a best practice to do so.
For example, perhaps my `calculate_price` function only depends on 2 attributes of the order which has 65 attributes. Am I creating a 2-element data type for that function to process? no! I'm specifying that it processes an Order data type, with all its 65 elements. But implicitly then I'm saying the function has 65 input parameters of all these specific types and nobody can call it now without providing them all. What a pain! Huge amount of extra code, refactoring, unit testing, because of this.
So either you end up with a cambrian explosion of micro-types or you have these way overspecified interfaces everywhere.
Compare with dynamic languages (or structural typing, Go etc) that only care that things "quack like a duck". The calculate_price function doesn't care what object you give it, as long as it has the two attributes it needs. Now I can unit test `calculate_price` with a 2-element object rather than needlessly creating the 23 irrelevant required elements of a valid Order.
I think a lot could be solved with culture shift. Where data types are really known and locked in, use the crap out of them. As soon as things get ambiguous or flexible, go right ahead and specify that your function takes a Map. If a useful concrete interface emerges at some point factor it out then. The problem is that this is really frowned upon in a lot of places.