I now realise that there are several issues conflated into a false dichotomy of static/dynamic.

  1. type expressivity (ML, Haskell, and Scala even more so)
  2. type checking (same family)

Traditional C and Java family languages fail completely on the first point. They have primitive type systems. Dynamic languages (PHP, Python, Ruby, Scheme, etc) obviously fail on the second point. So that covers about 90 or 95% of what most people are using.

If you address both these points, you have a very high level of expressive power (1) and safety (2).