Видимо, у меня какое-то не такое восприятие, но мне вопрос, вынесенный в название темы, кажется странным.
Программист, когда пишет функцию, он же представляет себе, что именно функция принимает и возвращает? Если нет, то это просто не имеет смысла: функция принимает на вход непонятно что и возвращает непонятно что. Над "непонятно чем" невозможно выполнить никаких операций. Очевидно, программист все же имеет в виду какой-то тип, пусть и не определенный формально и точно, но если над объектом производят хоть какие-то операции, то тип этими операциями и определяется.
С моей точки зрения, динамическая типизация является лишь неявной статической типизацией, просто, вместо явного объявления типа программистом, этот тип определяется через использование. Сам код задает контракт и, таким образом, тип.
Статическая типизация не просто "ограничивает", а определяет смысл выражений. У меня такое ощущение, что многие просто ее неправильно воспринимают, может быть, из-за отсутствия языков с адекватной типизацией.
Да и на практике в динамических языках все очень пошло заканчивается тем, что типы прописываются в комментариях, неформально и без проверки компилятором.