As part of my BSc project I explore design decisions in programming languages.

What is static typing?

Static typing means that the types of variables are declared upfront and variables may not change types. The opposite is dynamic typing, where variables have types that may change at runtime.

Static vs dynamic

Java has static typing. The variable example can only ever be an int.

int example = 5;
example = "Hello, world!"; // does not compile

Javascript has dynamic typing. The variable example changes type from number to string.

let example = 5;
example = "Hello, world!"; // compiles

Static typing reduces bugs

The paper To Type or Not to Type: Quantifying Detectable Bugs in JavaScript explores the relationship between static typing and the detection of type related errors.

Dynamic typing is simple to understand and its flexibility allows for more compact code. However, the paper shows that integrating type systems like Typescript and Flow into open source projects reduces bugs by 15%!

Static vs nominal vs manifest typing

We usually refer to languages as being "strongly" or "weakly" / "loosely" typed, referring to static and dynamic typing respectively.

Structured vs nominal

Structured typing means that types with the same structure are interchangeable, e.g. in Javascript.

function Human() {
    this.name = "Mieszko";

function Vehicle() {
    this.name = "Rolls Royce";

let mieszko = new Human();
let royce = new Vehicle();

function printName(human) {

printName(royce); // Works with Vehicle despite being made for Human

Java has nominal typing, so two classes with different names that are otherwise identical are not interchangeable.

Inferred vs manifest

Manifest typing is where variable types are explicitly declared.

Java has manifest typing. The variable example has type int and this is explicitly stated.

int example = 123;
example = "Hello, world!"; // does not compile

Rust has inferred typing. The compiler determines the type of example to be int.

let example = 123;
example = "Hello, world!"; // does not compile

Java and Rust both have static typing, so the type of example can never change.

Inferred typing is more difficult to implement but it can potentially save time because developers do not have to know the type of every variable, and with static typing IDEs can still show object members.