JavaScript has evolved from a Dynamically Typed to a Statically Typed Language
In any programming language a variable is simply a name of storage location. Similarly, in JavaScript a variable holds a reference to the location of the data in memory.
In JavaScript a variable name also holds the data type of the variable and it can be changed anytime. The variable’s data type is the JavaScript scripting engine’s interpretation of the type of data that variable is currently holding. A string variable holds a string, a number variable holds a number value, and so on.
let varOne = 10;
let varTwo = 20;
However, unlike many other languages, in JavaScript, the same variable can hold different types of data, all within the same application. This is a concept known by the terms loose typing/dynamic typing, both of which mean that a JavaScript variable can hold different data types at different times depending on context.
Loosely Typed Language/ Dynamically-typed language
With a loosely typed language, you don’t have to declare ahead of time that a variable will be a string or a number or a boolean, as the data type is actually determined while the application is being processed. If you start out with a string variable and then want to use it as a number you can do that
varTwo = '20';console.log(varOne + varTwo); // '1020'
The forgiving nature of loose typing can end up creating bugs in the code. If you try to add two numbers together, but the JavaScript engine interprets the variable holding one of them as a string data type, you end up with an odd string, rather than the sum you were expecting. Context is everything when it comes to variables and data types with JavaScript.
Statically-typed language
In a statically-typed languages the type checking is performed at compile time, whereas in a dynamically-typed languages the type checking is performed at runtime.
Lets understand what does ‘type-checking’ mean?
In Object Oriented Programming languages like Java and C++, when defining a variable, the ‘types’ refers to the type of data being defined by the variable . For example, in Java, a string variable is defined like this:
string myString = ‘hello’;
This has a correct type because the string annotation matches the value given to the mySting, as opposed to an integer or boolean. On the other hand, the following will fail to compile
string myString = true;
This happens because the variable has incorrect data type. We have explicitly stated myString as a string, but then defined it as the boolean true.
Statically-typed languages require you to declare the data types of your constructs before you can use them. Dynamically-typed languages do not.
The differences between static type checking and dynamic type checking matter most when a type error occurs. In a statically-typed language, type errors occur during the compilation step, that is, at compile time. In dynamically-typed languages, the errors occur only once the program is executed. That is, at runtime.
This means that a program written in a dynamically-typed language can compile even if it contains type errors that would otherwise prevent the script from running properly.
JavaScript as statically typed language
TypeScript has provided JavaScript developers an option to use static types. Lets understanding the syntax for static types.
let loading: boolean = false; // boolean
let num: number = 15; // integer
let str: string = 'xyz'; // string
Here, loading, num and str are variable names; boolean, number and string describes the type of variables. Variable name is followed by colon+space and then type of variable.
Advantages of using static types:
Static types offer many benefits when writing programs. You can detects bugs and errors early by checking to verify that the invariant we specified is true without actually running the program.
For example: A function that takes a number and calculates the square of a given number:
const calculateSquare = (num) => num * num;const square = calculateSquare(3); // 9
Now, if we were to pass a value which is not a number (e.g. ‘abc’)
var square= calculateSquare(‘abc’); // NaN
If some piece of functionality relied on this calculateSquare function always returning a number, then this result might lead to a bug or crash.
If we use static types, we can specify the exact input and output types for the function. (The following code was written in script.ts file which was then compiled to a script.js file)
const calculateSquare = (num: number): number => num * num;let newString: string = 'abc';calculateSquare(newString);
If we pass anything but a number into our calculateSquare function we get this error at the compile time:
script.ts:5:29 - error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.~~~~~~~~~
So we are assured that the function will only ever accept valid numbers as inputs and return a valid number as output. And this behaviour will ensure that we don’t get bugs at runtime.