What is typescript?

What is typescript?

The short answer to this question is Javascript with static typing, but we can dig deeper into what static typing is, why is it cool and also some other features typescript offers.

Types

To understand what Typescript offers to Javascript, we first need to understand what types are. Types in a programming language refer to the kind or type of information a given program stores. Programming languages usually have built in data types.

There are six basic data types in JavaScript which can be divided into three main categories: primitive, composite, and special data types. String, Number, and Boolean are primitive data types. Object, Array, and Function (which are all types of objects) are composite data types. Whereas Undefined and Null are special data types.

Primitive data types can hold only one value at a time, whereas composite data types can hold collections of values and more complex entities.

Strings

The string data type is used to represent textual data (i.e. sequences of characters). Strings are created using single or double quotes surrounding one or more characters, as shown below:

var a = 'Hi there!';

Numbers

The number data type is used to represent positive or negative numbers with or without decimal place, or numbers written using exponential notation e.g. 1.5e-4 (equivalent to 1.5x10-4).

var a = 25;

The Number data type also includes some special values which are: Infinity, -Infinity and NaN. Infinity represents the mathematical Infinity ∞, which is greater than any number. Infinity is the result of dividing a nonzero number by 0. While NaN represents a special Not-a-Number value. It is a result of an invalid or an undefined mathematical operation, like taking the square root of -1 or dividing 0 by 0, etc.

Booleans

The Boolean data type can hold only two values: true or false. It is typically used to store values like yes (true) or no (false), on (true) or off (false), etc. as demonstrated below:

var isReading = true;

Undefined

The undefined data type can only have one value-the special value undefined. If a variable has been declared, but has not been assigned a value, has the value undefined.

var a;
console.log(a) // Output: undefined

Null

A null value means that there is no value. It is not equivalent to an empty string ("") or 0, it is simply nothing.

Objects

The object is a complex data type that allows you to store collections of data. An object contains properties, defined as a key-value pair. A property key (name) is always a string, but the value can be any data type, like strings, numbers, booleans, or complex data types like arrays, function and other objects.

var car = {
    modal: "BMW X3",
    color: "white",
    doors: 5
}

Arrays

An array is a type of object used for storing multiple values in single variable. Each value (also called an element) in an array has a numeric position, known as its index, and it may contain data of any data type-numbers, strings, booleans, functions, objects, and even other arrays. The array index starts from 0, so that the first array element is arr[0] not arr[1].

var colors = ["Red", "Yellow", "Green", "Orange"];
console.log(colors[0]);   // Output: Red

Functions

The function is callable object that executes a block of code. Since functions are objects, so it is possible to assign them to variables, as shown in the example below:

var greeting = function(){ 
    return "Hello World!";
    console.log(greeting());     // Output: Hello World!
}

What's the deal with types and javascript

JavaScript is a loosely typed and dynamic language. Variables in JavaScript are not directly associated with any particular value type, and any variable can be assigned (and re-assigned) values of all types:

let foo = 42;    // foo is now a number
foo     = 'bar'; // foo is now a string
foo     = true;  // foo is now a boolean

This was done by design at the creation of javascript, since it was meant to be a scripting language friendly to both programmers and designers and used to add functionality to websites. The thing is javascript grew a lot with the years and started to be used to build huge applications. And when building huge applications, dynamic types can lead to silly bugs in the code base.

Let's see this with a simple example. Say we have a function that receives three parameters and returns a string

const personDescription = (name, city, age) => `${name} lives in ${city}. he's ${age}. In 10 years he'll be ${age+10}`

If we call the function this way we get the correct output:

console.log(personDescription('Germán', 'Buenos Aires', 29)) // output: Germán lives in Buenos Aires. he's 29. In 10 years he'll be 39.

But if accidentally we pass the function the third parameter as a string, we get a wrong output:

console.log(personDescription('Germán', 'Buenos Aires', '29')) // output: Germán lives in Buenos Aires. he's 29. In 10 years he'll be **2910**.

No error is shown by javascript because the program doesn't have a way of knowing what type of data the function should receive. It just takes the parameters we gave and performs the action we programmed, independently of the data type.

This error can easily be made by a developer, specially when working with big code bases and being unfamiliar with parameters required by functions or APIs, and this is exactly what Typescript comes to solve.

Typescript

In typescript, much like in other programming languages such as Java or C#, we need to declare the data type whenever we create a data structure. By declaring the data type, we give the program information to later on evaluate if the values assigned to that data structure match the data types declared or not. If there's a match, the program runs, and if not, we get an error. And these errors are very valuable, because as developers we can catch the bugs earlier. ;)

Let's repeat the previous example but now with typescript. In typescript, my function would look like this (see that it's exactly the same, only that besides each parameter I'm declaring it's data type):

const personDescription = (name: string, city: string, age: number) => `${name} lives in ${city}. he's ${age}. In 10 years he'll be ${age+10}.`

Now if I try to call the function with the wrong parameter data type, I get the following error output:

console.log(personDescription('Germán', 'Buenos Aires', '29')) // Error: TSError: ⨯ Unable to compile TypeScript: Argument of type 'string' is not assignable to parameter of type 'number'.

The beauty of typescript is that It's still easy as always javascript code, we only add the type declarations to it. That's why typescript is called a javascript superset, Typescript only adds certain features to Javascript.

Typescript basics

Types by Inference

TypeScript knows the JavaScript language and will generate types for you in many cases. For example in creating a variable and assigning it to a particular value, TypeScript will use the value as its type.

let helloWorld = "Hello World";

By understanding how JavaScript works, TypeScript can build a type-system that accepts JavaScript code but has types. This offers a type-system without needing to add extra characters to make types explicit in your code. That’s how TypeScript knows that helloWorld is a string in the above example.

Defining Types

TypeScript supports an extension of the JavaScript language, which offers places for you to tell TypeScript what the types should be.

The syntax to do so is quite simple, you just add a colon and it's type to the right of whatever you're declaring.

For example, when declaring a variable:

let myName: string = 'Germán'

If I try to reassign this to a number, I'll get the following error:

myName = 36 // Error: Type 'number' is not assignable to type 'string'.

Interfaces

When working with objects, we have a different syntax for declaring types which is called an interface. An interface looks a lot like a javascript object, just that we use the interface keyword, we don't have an equal sign or commas, and besides each key we have its data type instead of its value.

Later on, we can declare this interface as the data type of any object:

interface myData {
    name: string
    city: string
    age: number
}

let myData: myData = {
    name: 'Germán',
    city: 'Buenos Aires',
    age: 29
}

Say again I pass the age as a string, I'll get the following error:

let myData: myData = {
    name: 'Germán',
    city: 'Buenos Aires',
    age: 29 // Output: Type 'string' is not assignable to type 'number'.
}

If for example I wanted to make a key conditional, allowing it to be present or not, we just need to add a question mark at the end of the key in the interface:

interface myData {
    name: string
    city: string
    age?: number
}

If I want a variable to be able to be assigned more than one different data type, I can declare so by using unions as following:

interface myData {
    name: string
    city: string
    age: number | string
}

let myData: myData = {
    name: 'Germán',
    city: 'Buenos Aires',
    age: '29' // I get no error now
}

Functions and arrays

When typing functions, we can type its parameters as well as its return value:

interface myData {
    name: string
    city: string
    age: number
    printMsg: (message: string) => string
}

let myData: myData = {
    name: 'Germán',
    city: 'Buenos Aires',
    age: 29,
    printMsg: (message) => message
}

console.log(myData.printMsg('Hola!'))

For typing arrays the syntax is the following:

let numbersArray: number[] = [1, 2, 3] // We only accept numbers in this array
let numbersAndStringsArray: (number|string)[] = [1, 'two', 3] // Here we accept numbers and strings.

Tuples are arrays with fixed size and types for each position. They can be built like this:

let skill: [string, number];
skill = ['Programming', 5];

Typescript's compiler

The way typescript checks the types we've declared is through its compiler. A compiler is a program that converts our code to machine code prior to its execution.

So every time we run our typescript file, typescript converts our code and at that point checks the types. Only if everything is ok the program runs. That's why we can get errors detected prior to program execution.

On the other hand, in javascript types are checked at run time. That means types are not checked until the program executes.

Something important to mention is that typescript transpiles code into javascript. Browsers don't read typescript, but they can execute typescript written programs because the code is converted to javascript.

We can also select to what "flavor" of javascript we wan't to transpile to, for example es4, es5, etc. This and many other options can be configured from the tsconfig.json file its generated every time we create a typescript project.

{
  "compilerOptions": {
    "module": "commonjs",
    "esModuleInterop": true,
    "target": "es6",
    "moduleResolution": "node",
    "sourceMap": true,
    "outDir": "dist"
  },
  "lib": ["es2015"]
}

Other functionalities of Typescript

Typescript can also be considered as a linter, a tool that makes real time suggestions to the developer as code is being written. Specially when combined with VS Code, typescript can make some sweet suggestions based on our declared types that often save time and errors to us.

Another functionality typescript has is as a documentation tool. Imagine you get a new job and you have to get to know a huge code base. Having the types declared for each function is of huge help when using them for the first time and reduces the learning curve for any project.

Roundup

So that are the basics of typescript. It can be easily explained as javascript with static typing, but we also saw Typescript has its own compiler and can be though of as a linter and a documentation tool too.

If my article was helpful, consider inviting me a coffee = )

Invitame un café en cafecito.app

Buy me a coffee

You can also follow me on Twitter and Linkedin