La escritura fuerte / débil y la escritura estática / dinámica son ortogonales.
Fuerte / débil se trata de si el tipo de valor importa, funcionalmente hablando. En un lenguaje de tipo débil, puede tomar dos cadenas que están llenas de dígitos y realizar la suma de enteros; en un lenguaje fuertemente tipado, esto es un error (a menos que primero convierta o convierta los valores a los tipos correctos). La escritura fuerte / débil no es una cosa en blanco y negro; la mayoría de los idiomas no son 100% estrictos ni 100% débiles.
La tipificación estática / dinámica se trata de si los tipos se unen a valores o identificadores. En un lenguaje de tipo dinámico, puede asignar cualquier valor a cualquier variable, independientemente del tipo; la escritura estática define un tipo para cada identificador, y la asignación de un tipo diferente es un error o da como resultado una conversión implícita. Algunos idiomas adoptan un enfoque híbrido, lo que permite tipos declarados estáticamente, así como identificadores sin tipo ('variante'). También hay inferencia de tipos, un mecanismo en el que es posible escribir de forma estática sin declarar explícitamente el tipo de todo, al hacer que el compilador descubra los tipos (Haskell lo usa ampliamente, C # lo expone a través de la var
palabra clave).
La programación dinámica débil permite un enfoque pragmático; el idioma no se interpone en tu camino la mayor parte del tiempo, pero tampoco intervendrá cuando te disparas en el pie. Por el contrario, la escritura estática fuerte empuja al programador a expresar ciertas expectativas acerca de los valores explícitamente en el código, de manera que permita al compilador o al intérprete detectar una clase de errores. Con un buen sistema de tipos, un programador puede definir exactamente qué se puede y qué no se puede hacer con un valor, y si, por accidente, alguien intenta algo indeseable, el sistema de tipos a menudo puede evitarlo y mostrar exactamente dónde y por qué las cosas salen mal.