Pisanie mocne / słabe oraz pisanie statyczne / dynamiczne są ortogonalne.
Mocna / słaba dotyczy tego, czy rodzaj wartości ma znaczenie, mówiąc funkcjonalnie. W słabo wpisanym języku możesz wziąć dwa ciągi, które są wypełnione cyframi i wykonać na nich dodawanie liczb całkowitych; w silnie napisanym języku jest to błąd (chyba że najpierw rzutujesz lub konwertujesz wartości na poprawne typy). Mocne / słabe pisanie nie jest czymś czarno-białym; większość języków nie jest ani w 100% ścisła, ani w 100% słaba.
Wpisywanie statyczne / dynamiczne dotyczy tego, czy typy wiążą się z wartościami, czy z identyfikatorami. W języku dynamicznie wpisywanym możesz przypisać dowolną wartość dowolnej zmiennej, niezależnie od typu; typowanie statyczne definiuje typ dla każdego identyfikatora, a przypisywanie z innego typu jest błędem lub skutkuje niejawnym rzutowaniem. Niektóre języki przyjmują podejście hybrydowe, dopuszczając zarówno statycznie deklarowane typy, jak i nietypowe identyfikatory („wariant”). Istnieje również wnioskowanie o typie, mechanizm, w którym możliwe jest pisanie statyczne bez jawnego deklarowania typu wszystkiego, poprzez kompilator rozróżniający typy (Haskell używa tego szeroko, C # eksponuje to poprzez var
słowo kluczowe).
Słabe dynamiczne programowanie pozwala na pragmatyczne podejście; język przez większość czasu ci nie przeszkadza, ale też nie wkracza, gdy strzelasz sobie w stopę. Natomiast silne pisanie statyczne popycha programistę do wyraźnego wyrażenia pewnych oczekiwań dotyczących wartości w kodzie, w sposób umożliwiający kompilatorowi lub interpreterowi wykrycie klasy błędów. Przy dobrym systemie typów programista może dokładnie zdefiniować, co można, a czego nie można zrobić z wartością, a jeśli przypadkiem ktoś spróbuje czegoś niepożądanego, system typów może często temu zapobiec i dokładnie pokazać, gdzie i dlaczego coś idzie nie tak.