Tipagem forte / fraca e tipagem estática / dinâmica são ortogonais.
Forte / fraco é sobre se o tipo de valor é importante, funcionalmente falando. Em um idioma de tipo fraco, você pode pegar duas cadeias que são preenchidas com dígitos e executar a adição de números inteiros; em um idioma de tipo forte, isso é um erro (a menos que você converta ou converta os valores nos tipos corretos primeiro). A digitação forte / fraca não é uma coisa em preto e branco; a maioria dos idiomas não é 100% rigorosa nem 100% fraca.
A digitação estática / dinâmica é sobre se os tipos se ligam a valores ou a identificadores. Em um idioma de tipo dinâmico, você pode atribuir qualquer valor a qualquer variável, independentemente do tipo; a digitação estática define um tipo para cada identificador e a atribuição de um tipo diferente é um erro ou resulta em uma conversão implícita. Algumas linguagens adotam uma abordagem híbrida, permitindo tipos declarados estaticamente, bem como identificadores não tipados ('variante'). Também há inferência de tipo, um mecanismo em que a digitação estática é possível sem declarar explicitamente o tipo de tudo, fazendo com que o compilador descubra os tipos (Haskell usa isso extensivamente, o C # o expõe por meio da var
palavra - chave).
A programação dinâmica fraca permite uma abordagem pragmática; o idioma não fica no seu caminho a maior parte do tempo, mas também não entra em cena quando você leva um tiro no pé. A digitação estática forte, por outro lado, leva o programador a expressar determinadas expectativas sobre valores explicitamente no código, de uma maneira que permita ao compilador ou intérprete detectar uma classe de erros. Com um bom sistema de tipos, um programador pode definir exatamente o que pode ou não ser feito com relação a um valor e, por acidente, alguém tenta algo indesejado, o sistema de tipos geralmente pode impedi-lo e mostrar exatamente onde e por que as coisas dão errado.