Пришла тут в голову забавная на мой взгляд идея. Берём динамически типизированный язык вроде жаваскрипта. Пишем код. Пишем тесты. Прогоняем тесты. И вот тут запоминаются все типы, которые приходили и уходили в функцию. После этого функцию нельзя вызывать с другими типами. Будет ошибка компиляции.
Я немного сумбурно это расписал, но постарался выразить главную идею. Типы объявляются опосредованно, через тесты.