Static Type Checking of Variables

Unrestricted Assignment to var & let Variables in JavaScript

In JavaScript, a value reference of a variable declared with var can be changed at runtime not only to another reference to a value of the same type but to another reference to a value of any type whatsoever.

// Pure JavaScript
var foo = 'forty two'
foo = 'forty three' // Acceptable assignment.
foo = 42 // Also acceptable assignment.

Similarly, a value reference of a variable declared with ES6 let can be changed at runtime not only to another reference to a value of the same type but to another reference to a value of any type whatsoever.

// ES6
let foo = 'forty two'
foo = 'forty three' // Acceptable assignment.
foo = 42 // Also acceptable assignment.

On the other hand, a reference to a value of a variable declared with ES6 const cannot be changed at all.

// ES6
const foo = 'forty two'
foo = 'forty three' // Uncaught TypeError: Assignment to constant variable.

This does not mean that the value referenced by a variable declared with ES6 const cannot change. Only the reference to that value is constant.

// ES6
const foo = []
foo.push(42)
console.log(foo) // [42]

Restricting Assignment to var & let Variables in TypeScript

Contrary to JavaScript, in TypeScript, it is possible to restrict the type of value allowed to be referenced by a given variable declared with var or let.

To restrict a type of a value allowed to be assigned to a variable follow the variable name with : and provide the type. This is called variable type annotation.

// TypeScript
let foo: string = 'forty two'
foo = 'forty three' // Acceptable assignment.
foo = 42 // TS: Type 'number' is not assignable to type 'string'.

let bar: number[] = [42]
bar = [43] // OK.
bar = ['forty two'] // Type 'string' is not assignable to type 'number'.

Variable Type Inference in TypeScript

For a variable declared with let or var, when no type is explicitly annotated, TypeScript implicitly infers the type of value allowed to be referenced by that variable.

// TypeScript
let foo = 'forty two' // TypeScript infers the type of foo to be type 'string'.
foo = 'forty three'  // Acceptable assignment.
foo = 42 // TS: Type 'number' is not assignable to type 'string'.

let bar = [42] // TypeScript infers the type of foo to be 'number[]'.
bar = [43] // OK.
bar = ['forty two'] // TS: Type 'string' is not assignable to type 'number'.