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'.