As the power of TypeScript has been rising during the last few years, thousands of developers decided to start using this Javascript superset to empower their code even more. This guide aims to be a quick primer for all the developers out there who would like to learn how to use TypeScript and use it in their next project. 

#1 The word Types means: use them!

One of the biggest features of TypeScript is compile time type-checking to prevent any mismatch in the types you are using for your variables and yes, you can actually use types in TypeScript, here are some examples about how you can use them: 

// legal
let isReady : boolean = false; 
let decimal : number = 20;     
let name    : string = "Dev.to";
let numbers : number[] = [1,2, 3]; 

// illegal
let isReady : boolean = 10; 
let decimal : number = "not a number";     
let name    : string = true;
let numbers : number[] = "not an array of numbers"; 

#1.1 Can I use multiple types for my variables?

Of course you can, by simply using the any type for one of your variables you will be able to assign different value types like: 

let unknown : any = 30; 
unknown = "what is this variable?";

If you want to restrict the types you can assign to your variables, you can eventually use the pipe operator like this: 

let multiple : boolean | number = 10; 
multiple = true; // still valid

#1.2 What if don’t want to specify the type of a variable?

No problem! TypeScript supports both implicit and explicit typing. In the first case, you will be specifying variables’ types precisely like we have seen up to this point, in the second case, the type will be automatically assigned to a variable whenever you first initialize it a value, this mechanism is better known as type inference.  

let explicit : number = 10; // explicitily using the type 'number'
let implicit = 10; // inference of the type 'number'

Notice how type inference comes in handy in other useful cases like function return values: 

// inference will set 'number' as the return type for this function
function add(a: number, b: number) {
    return a + b;
}

#1.3 Can I check the type of my variables?

Wanna make sure you are using the right type? the right class? you can use that by using the instanceof operator like this: 

import { Cake } from './cake.model'; 
let cake = new Cake('eggs', 'milk');

if (cake instanceof Cake) {
    console.log("We've got a cake here!"); 
}

This is especially useful for user defined types and it will also work when you are inheriting properties from another object. 

#1.4 Can I convert the types of my variables?

This type of operation is typically known as casting and it can be performed in special cases in TypeScript where we might need to handle a variable using a specific type. Let’s suppose you defined a variable of type any but you now want to use some common string functions on that variable that you cannot access now since the type is not string, you can tell TypeScript to handle that variable as a such using: 

let unknown : any; 
let unknown = "hello"; 

console.log("length is : ", (<string>unknown).length); 

#2 Working with Arrays

Everything that mentioned above can be pretty much adapted when it comes to using Arrays in TypeScript: 

// legal
let numbers : number[] = [1, 2, 3]; 
let strings: string[] = ["hello", "good", "world"]; 
let booleans : boolean[] = [true, false, true]; 
let whatever: any[] = ['Hello World', 10];


// illegal 
let numbers : numbers[] = [1, true, 3]; 
let strings: string[] = ["hello", 1, "world"]; 
let booleans : boolean[] = [true, 100, true]; 

// other possibilities include
let numbersAndBooleans = (number | boolean) = [true, 100]; // using the pipe operator
let matrix = number[][] = [[10, 20]]; 

#2.1 Using tuples

Quite a new concept, tuple types allow you to express an array where the type of a fixed number of elements is known, but need not be the same. Consider if you wanted to represent a value as a pair of a boolean and a number:

// Using a tuple
let x: [boolean, number];
x = [true, 10]; // initialization
x = [10, "hello"]; // illegal initialization

#2.2 Something I really missed: Enums!

This great addition to Javascript is something that I was really missing from the old days when I would code using Java, enums are basically a set of named constants. There are three types of enums: 

  • Numeric Enum
  • String enum
  • Heterogeneous enum

In order to not make this article too long, I won’t go into too much detail about enums, just remember that they are especially useful if you want to better document your intent or to create a set of distinct cases like: 

enum Direction { 
    Up = 1,
    Down,
    Left,
    Right,
}
movePlayer(Direction.Up); 

#3 What about objects?

Objects are another important part of Typescript, let’s try to analyze them in better detail with an example: 

// Javascript definition
let user = {
name: "piero", 
surname: "borrelli"
}

// Typescript definition is the same
let user = {
name: "piero", 
surname: "borrelli"
}

// except that now name and surname will be considered as
{name: string, surname: string}

The two properties of the objects we have are inferenced to type string, meaning that any attempt to assign a value of different type to them will be invalid: 

    user.name = 35; // invalid

#3.1 Object type

Object is a type that doesn’t fall in the primitive-type category like: boolean, string, number, symbol, null, undefined and it follows this syntax: 

    let user: { name: string, surname: string};

#4 Functions

When it comes to functions, Typescript introduces the possibilty to use types when working with them, the first place we want to use them for example is for function parameters: 

// define types for the function parameters
function test(name: string, surname: string) {
 return name + " " + surname;  
}

let fullName = test("piero", "borrelli"); // legal
let fullName = test(10, "borrelli"); // illegal

Another place where you might want to specify a type is when returning a value from a function. Notice that, in the case of the function above, the return type was automatically infered to be of type string. Let’s see how we can explicitly define the return type of a function using: 

// define return type for the function
function test(name: string, surname: string): string {
 return name + " " + surname;  
}

// illegal
function test(name: string, surname: string): string {
 return name.length; // will return a number here which is not expected  
}

#5 The OOP part

Since the release of ECMAScript 6, Javascript programmers have been able to build their programs using the object-oriented approach. This approach is also supported by Typescript, so let’s try to analyze how we would use it by making some examples: 

class Point{
    x: number;
    y: number; 
    constructor(x: number, y: number) {
        this.x = x; // where 'this' refers to the current object
        this.y = y; 
    }
    getPoints() {
        return "x: " + this.x + " y: " + this.y;
    }
}

let Point = new Point(10, 20);

To most of the people out there who have worked with languages like C# or Java this will look extremely familiar, we have a class named Point that has two members x and y, we can access them freely (more on this later) and we also call a class method called getPoints(). We can then create an instance of an object of type Point by using the new keyword. 

Using access modifiers

Not going on too much detail on this since it’s a complete different topic, but keep in mind that in Typescript you can also define access modifiers for your classes’ variables like this: 

class Point{
   private x: number;
   private y: number; 
    constructor(x: number, y: number) {
        this.x = x; // where 'this' refers to the current object
        this.y = y; 
    }
    getPoints() {
        return "x: " + this.x + " y: " + this.y;
    }
}

As with basically all the object oriented programming languages, we can use access modifiers to establish who is going to be able to access our class data. By default, public is set as a member default modifier, private and protected are used respectively when you want a member to not be accessible outside of its class(private) and when you want a member to be accessible only inside its class or deriving classes. 

Inheritance

As already mentioned earlier, Typescript supports the most used object-oriented patterns including inheritance. So using Typescript you will be able to define a class and then define a subclass of it which will inherit the superclass base methods and members: 

class Animal {
    move(steps: number = 0) {
        console.log(`Animal moved ${steps}m.`);
    }
}

class cat extends Animal {
    meow() {
        console.log('Meow');
    }
}

const cat= new Cat();
cat.meow();
cat.move(1000);

Interfaces

Another common object oriented technique that you might to use it to create an interface. This in possible in Typescript, where the main focus is type-checking, we can use interfaces to give names to these types. So basically when using them we will be creating a group of related methods and members that will describe a particular object: 

interface Box{
   width: number, 
   height: number
}

Conclusion

The idea behind this article was just to be able to give you a quick primer on what you can do with Typescript, how it can help us solve common problems and its different approach with Javascript.
Hope it gave you a new vision on something useful!

If you are interested in going into more detail with TypeScript, you can checkout these resources: here and here


Thanks for reading, 

Piero Borrelli. 

LEAVE A REPLY

Please enter your comment!
Please enter your name here