Dynamic typing simply works better when you're dealing with external-interfaces that are dynamic in nature (i.e. data-structures and interfaces defined outside of your software). Web applications, because they deal with a lot of text-manipulation and because they also deal with external data-sources and multiple layers, are the prime example for which dynamic typing works best.
Why do you say that optional static typing
introduced into dynamic languages is a divergence?
Is not a divergence per-se, but the purpose of static types is to prove correctness of types from compile-time. Dynamic languages (as they are used) only need static types for performance reasons, that's why the optimal implementation will consider these types as hints and nothing else. what part of OOP do you see as incompatible
with typing
A static-typing system, to function properly, must be able to trace the true type of a variable throughout the code and be able to use that type at any given time in the compilation process.In OOP you don't know the type of variables at any given time, you can only know its interface at most. And even that is incompatible with OOP, as OOP was also designed around the idea of overriding the method-dispatching being done (even in Java/Scala, all method-dispatching is done at runtime, as you're dispatching based on the implicit parameter).
For example, Scala cannot implement the Hindley–Milner algorithm for type-inference, being forever forced to the current poor implementation that only deals with inferring the type of local variables. And F# / Ocaml on the other hand really have 2 type-systems in a single language (to be able to keep Hidley-Milner , with rules for interoperability. And when working with one or the other, it's like working with different languages.
And the truth of the matter is, if you're watching closely, hybrid languages that are trying to combine static and dynamic really give you the worst of both worlds.