[type-safety] What is the difference between a strongly typed language and a statically typed language?

Also, does one imply the other?

This question is related to type-safety strong-typing static-typing

The answer is


One does not imply the other. For a language to be statically typed it means that the types of all variables are known or inferred at compile time.

A strongly typed language does not allow you to use one type as another. C is a weakly typed language and is a good example of what strongly typed languages don't allow. In C you can pass a data element of the wrong type and it will not complain. In strongly typed languages you cannot.


Strongly typed means that there are restrictions between conversions between types.

Statically typed means that the types are not dynamic - you can not change the type of a variable once it has been created.


Both are poles on two different axis:

  • strongly typed vs. weakly typed
  • statically typed vs. dynamically typed

Strongly typed means, a will not be automatically converted from one type to another. Weakly typed is the opposite: Perl can use a string like "123" in a numeric context, by automatically converting it into the int 123. A strongly typed language like python will not do this.

Statically typed means, the compiler figures out the type of each variable at compile time. Dynamically typed languages only figure out the types of variables at runtime.


Data Coercion does not necessarily mean weakly typed because sometimes its syntacical sugar:

The example above of Java being weakly typed because of

String s = "abc" + 123;

Is not weakly typed example because its really doing:

String s = "abc" + new Integer(123).toString()

Data coercion is also not weakly typed if you are constructing a new object. Java is a very bad example of weakly typed (and any language that has good reflection will most likely not be weakly typed). Because the runtime of the language always knows what the type is (the exception might be native types).

This is unlike C. C is the one of the best examples of weakly typed. The runtime has no idea if 4 bytes is an integer, a struct, a pointer or a 4 characters.

The runtime of the language really defines whether or not its weakly typed otherwise its really just opinion.

EDIT: After further thought this is not necessarily true as the runtime does not have to have all the types reified in the runtime system to be a Strongly Typed system. Haskell and ML have such complete static analysis that they can potential ommit type information from the runtime.


Strong typing probably means that variables have a well-defined type and that there are strict rules about combining variables of different types in expressions. For example, if A is an integer and B is a float, then the strict rule about A+B might be that A is cast to a float and the result returned as a float. If A is an integer and B is a string, then the strict rule might be that A+B is not valid.

Static typing probably means that types are assigned at compile time (or its equivalent for non-compiled languages) and cannot change during program execution.

Note that these classifications are not mutually exclusive, indeed I would expect them to occur together frequently. Many strongly-typed languages are also statically-typed.

And note that when I use the word 'probably' it is because there are no universally accepted definitions of these terms. As you will already have seen from the answers so far.


Answer is already given above. Trying to differentiate between strong vs week and static vs dynamic concept.

What is Strongly typed VS Weakly typed?

Strongly Typed: Will not be automatically converted from one type to another

In Go or Python like strongly typed languages "2" + 8 will raise a type error, because they don't allow for "type coercion".

Weakly (loosely) Typed: Will be automatically converted to one type to another: Weakly typed languages like JavaScript or Perl won't throw an error and in this case JavaScript will results '28' and perl will result 10.

Perl Example:

my $a = "2" + 8;
print $a,"\n";

Save it to main.pl and run perl main.pl and you will get output 10.

What is Static VS Dynamic type?

In programming, programmer define static typing and dynamic typing with respect to the point at which the variable types are checked. Static typed languages are those in which type checking is done at compile-time, whereas dynamic typed languages are those in which type checking is done at run-time.

  • Static: Types checked before run-time
  • Dynamic: Types checked on the fly, during execution

What is this means?

In Go it checks typed before run-time (static check). This mean it not only translates and type-checks code it’s executing, but it will scan through all the code and type error would be thrown before the code is even run. For example,

package main

import "fmt"

func foo(a int) {
    if (a > 0) {
        fmt.Println("I am feeling lucky (maybe).")
    } else {
        fmt.Println("2" + 8)
    }
}

func main() {
    foo(2)
}

Save this file in main.go and run it, you will get compilation failed message for this.

go run main.go
# command-line-arguments
./main.go:9:25: cannot convert "2" (type untyped string) to type int
./main.go:9:25: invalid operation: "2" + 8 (mismatched types string and int)

But this case is not valid for Python. For example following block of code will execute for first foo(2) call and will fail for second foo(0) call. It's because Python is dynamically typed, it only translates and type-checks code it’s executing on. The else block never executes for foo(2), so "2" + 8 is never even looked at and for foo(0) call it will try to execute that block and failed.

def foo(a):
    if a > 0:
        print 'I am feeling lucky.'
    else:
        print "2" + 8
foo(2)
foo(0)

You will see following output

python main.py
I am feeling lucky.
Traceback (most recent call last):
  File "pyth.py", line 7, in <module>
    foo(0)
  File "pyth.py", line 5, in foo
    print "2" + 8
TypeError: cannot concatenate 'str' and 'int' objects

This is often misunderstood so let me clear it up.

Static/Dynamic Typing

Static typing is where the type is bound to the variable. Types are checked at compile time.

Dynamic typing is where the type is bound to the value. Types are checked at run time.

So in Java for example:

String s = "abcd";

s will "forever" be a String. During its life it may point to different Strings (since s is a reference in Java). It may have a null value but it will never refer to an Integer or a List. That's static typing.

In PHP:

$s = "abcd";          // $s is a string
$s = 123;             // $s is now an integer
$s = array(1, 2, 3);  // $s is now an array
$s = new DOMDocument; // $s is an instance of the DOMDocument class

That's dynamic typing.

Strong/Weak Typing

(Edit alert!)

Strong typing is a phrase with no widely agreed upon meaning. Most programmers who use this term to mean something other than static typing use it to imply that there is a type discipline that is enforced by the compiler. For example, CLU has a strong type system that does not allow client code to create a value of abstract type except by using the constructors provided by the type. C has a somewhat strong type system, but it can be "subverted" to a degree because a program can always cast a value of one pointer type to a value of another pointer type. So for example, in C you can take a value returned by malloc() and cheerfully cast it to FILE*, and the compiler won't try to stop you—or even warn you that you are doing anything dodgy.

(The original answer said something about a value "not changing type at run time". I have known many language designers and compiler writers and have not known one that talked about values changing type at run time, except possibly some very advanced research in type systems, where this is known as the "strong update problem".)

Weak typing implies that the compiler does not enforce a typing discpline, or perhaps that enforcement can easily be subverted.

The original of this answer conflated weak typing with implicit conversion (sometimes also called "implicit promotion"). For example, in Java:

String s = "abc" + 123; // "abc123";

This is code is an example of implicit promotion: 123 is implicitly converted to a string before being concatenated with "abc". It can be argued the Java compiler rewrites that code as:

String s = "abc" + new Integer(123).toString();

Consider a classic PHP "starts with" problem:

if (strpos('abcdef', 'abc') == false) {
  // not found
}

The error here is that strpos() returns the index of the match, being 0. 0 is coerced into boolean false and thus the condition is actually true. The solution is to use === instead of == to avoid implicit conversion.

This example illustrates how a combination of implicit conversion and dynamic typing can lead programmers astray.

Compare that to Ruby:

val = "abc" + 123

which is a runtime error because in Ruby the object 123 is not implicitly converted just because it happens to be passed to a + method. In Ruby the programmer must make the conversion explicit:

val = "abc" + 123.to_s

Comparing PHP and Ruby is a good illustration here. Both are dynamically typed languages but PHP has lots of implicit conversions and Ruby (perhaps surprisingly if you're unfamiliar with it) doesn't.

Static/Dynamic vs Strong/Weak

The point here is that the static/dynamic axis is independent of the strong/weak axis. People confuse them probably in part because strong vs weak typing is not only less clearly defined, there is no real consensus on exactly what is meant by strong and weak. For this reason strong/weak typing is far more of a shade of grey rather than black or white.

So to answer your question: another way to look at this that's mostly correct is to say that static typing is compile-time type safety and strong typing is runtime type safety.

The reason for this is that variables in a statically typed language have a type that must be declared and can be checked at compile time. A strongly-typed language has values that have a type at run time, and it's difficult for the programmer to subvert the type system without a dynamic check.

But it's important to understand that a language can be Static/Strong, Static/Weak, Dynamic/Strong or Dynamic/Weak.