While static and dynamic typing is usually about when types are known, strong and weak typing is about how strict a language is with types.
Languages that are strongly typed take types seriously and will not allow arbitrary manipulation of types as you will. Python, for example will raise an exception if you decide to carry out an operation like so:
string_and_int_operation = "3" + 3 print(string_and_int_operation)
TypeError as exception type.
Python will not attempt to "make things work" by performing some unintended action.
This behavior is prevalent in most statically typed languages and is helpful to prevent unintended consequences as a result of operations between different types.
In weak typing on the other hand, the interpreter will carry out the operation regardless and yield a result. Whether the result is semantically correct or not is variable.
> "22" + 3 // will result in "223" > "22" - 3 // will result in 19
The concept of strongly and weakly typed languages are not exactly agreed upon by the programming community as it is a relative matter. At some point, even strongly typed languages like Python makes this operation a legal one:
"Hello " * 3 Hello Hello Hello
You'd rather compare languages in terms of static or dynamic typing rather than strong and weak, since it is what you're likely to be talking about to someone else.