Сильная / слабая типизация и статическая / динамическая типизация являются ортогональными.
Сильный / слабый - это вопрос о том, имеет ли значение тип значения с функциональной точки зрения. В слабо типизированном языке вы можете взять две строки, заполненные цифрами, и выполнить с ними целочисленное сложение; в строго типизированном языке это ошибка (если вы сначала не приведете значения или не преобразуете их в правильные типы). Сильная / слабая типизация - не черно-белая вещь; большинство языков не являются ни на 100% строгими, ни на 100% слабыми.
Статическая / динамическая типизация зависит от того, связаны ли типы со значениями или идентификаторами. В динамически типизированном языке вы можете назначить любое значение любой переменной независимо от ее типа; статическая типизация определяет тип для каждого идентификатора, а присвоение другого типа является либо ошибкой, либо приводит к неявному приведению. Некоторые языки используют гибридный подход, допускающий статически объявленные типы, а также нетипизированные идентификаторы («вариант»). Существует также вывод типа, механизм, в котором статическая типизация возможна без явного объявления типа всего, если компилятор выяснит типы (Haskell использует это широко, C # предоставляет его через var
ключевое слово).
Слабое динамическое программирование допускает прагматичный подход; язык не мешает вам в большинстве случаев, но он не вмешивается, когда вы стреляете себе в ногу. Напротив, строгая статическая типизация заставляет программиста явно выражать определенные ожидания относительно значений в коде таким образом, который позволяет компилятору или интерпретатору обнаруживать класс ошибок. С хорошей системой типов программист может точно определить, что можно и нельзя сделать со значением, и, если случайно кто-то попробует что-то нежелательное, система типов часто может предотвратить это и показать, где и почему что-то идет не так.