JavaScript is a dynamically typed language, meaning variables can change type
let foo = "hello";
foo = 55; // foo has changed type from a string to a number - no problem
In TypeScript the type of a variable cannot be changed at any point in a program
let foo = "hello";
foo = 55; // ERROR - foo cannot change from string to number
We can set the type we want a variable to be
by adding
:
type
after declaring a variable:
let id: number = 5;
let firstname: string = 'danny';
let hasDog: boolean = true;
let unit: number; // Declare variable without assigning a value
unit = 5;
It's called a Type annotation or Type signature
But it's usually best to not explicitly state the type, as TypeScript automatically infers the type of a variable:
let id = 5; // TS knows it's a number
let firstname = 'danny'; // TS knows it's a string
let hasDog = true; // TS knows it's a boolean
hasDog = 'yes'; // ERROR
It's called Type inference
We can also set a variable to be able to have two types.
let age: string | number;
age = 26;
age = '26';
This type called Union
We can define what the types the function arguments should be, as well as the return type of the function:
// Define a function called circle that takes a diam variable of type number, and returns a string
function circle(diam: number): string {
return 'The circumference is ' + Math.PI * diam;
}
console.log(circle(10)); // The circumference is 31.41592653589793
The same function, but with an ES6 arrow function:
const circle = (diam: number): string => {
return 'The circumference is ' + Math.PI * diam;
};
console.log(circle(10)); // The circumference is 31.41592653589793
It isn't necessary to explicitly state that circle is a function; TypeScript infers it. TypeScript also infers the return type of the function.
// Using explicit typing
const circle: Function = (diam: number): string => {
return 'The circumference is ' + Math.PI * diam;
};
// Inferred typing - TypeScript sees that circle is a function that always returns a string, so no need to explicitly state it
const circle = (diam: number) => {
return 'The circumference is ' + Math.PI * diam;
};
We can add a question mark after a parameter to make it optional.
const add = (a: number, b: number, c?: number | string) => {
console.log(c);
return a + b;
};
console.log(add(5, 4, 'I could pass a number, string, or nothing here!'));
// I could pass a number, string, or nothing here!
// 9
A function that returns nothing is said to return void – a complete lack of any value.
const logMessage = (msg: string): void => {
console.log('This is the message: ' + msg);
};
logMessage('TypeScript is superb'); // This is the message: TypeScript is superb
If we want to declare a function variable, but not define it (say exactly what it does), then use a function signature.
// Declare the varible sayHello, and give it a function signature that takes a string and returns nothing.
let sayHello: (name: string) => void;
// Define the function, satisfying its signature
sayHello = (name) => {
console.log('Hello ' + name);
};
sayHello('Danny'); // Hello Danny
Type Aliases can reduce code duplication, keeping our code DRY.
type StringOrNumber = string | number;
type PersonObject = {
name: string;
id: StringOrNumber;
};
const person1: PersonObject = {
name: 'John',
id: 1,
};
const person2: PersonObject = {
name: 'Delia',
id: 2,
};
const sayHello = (person: PersonObject) => {
return 'Hi ' + person.name;
};
const sayGoodbye = (person: PersonObject) => {
return 'Seeya ' + person.name;
};
Extra time that you have to spend writing more precise code and compiling will be more than saved by how many fewer bugs you'll have in your code.
For many projects – especially medium to large projects – TypeScript will save you lots of time and headaches.
And if you already know JavaScript, TypeScript won't be too hard to learn. It's a great tool to have in your arsenal.
If you have any questions leave them in the comments.