Detecting Errors Before Running Code With TypeScript
Tags: javascript, typescript
Published: 2021-05-10 18:25:06

---
image: "Images/detecting-errors-before-running-code-with-typescript.png"
title: "Detecting Errors Before Running Code With TypeScript"
tags: ["javascript", "typescript"]
keywords:
  [
    "javascript",
    "typescript",
  ]
published: true
canonical_url: "https://byte.ski/blog/article/detecting-errors-before-running-code-with-typescript"
cover_image: "https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tur7xnq09ejp6uvmezwj.png"
---

This post is part of series and [book about TypeScript](https://byte.ski/typescript-book). It will guide you from scratch to writing full TypeScript applications on Back End and Front End. The series is available as **PDF eBook** for **free** to **everyone**.

<a href="https://byte.ski/typescript-book"><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/idg3cmsrhuu0jqx5bulp.png" alt="TypeScript Book (PDF)" /></a>   

## The problem

In the [previous post](https://byte.ski/blog/article/typescript-what-is-all-about-and-why-should-you-use-it) we talked about what is [TypeScript](https://byte.ski/notes/TypeScript) and why should we use that. Now it's time to go to practice.

We need to know how to start using [TypeScript](https://byte.ski/notes/TypeScript) in our [JavaScript](https://byte.ski/notes/JavaScript) project. In examples of this post series, I will use mostly code that written in [Node](https://byte.ski/notes/Node) environment. It won't be any specific code that is understandable for only developers who worked with [Node](https://byte.ski/notes/Node) before. Because this material is about TypeScript I want to specify more on TypeScript itself. 

Okay, let's start with an introduction to our first example. Here we have a very simple command-line application that works on [Node](https://byte.ski/notes/Node). This example consists of one file. Let name it **sum.js**. When we execute this file by Node it will ask two questions in the Terminal - a value of argument X and Y. After typing these values the app will print the result of *X + Y*.

> An example of this code is written with [[Node]]. If Node is not installed on your machine, check out the post about [How To Install or Update Node by Using nvm (Node Version Manager)](https://byte.ski/blog/article/how-to-install-or-update-node-by-using-nvm).

Look at the code:

```js
const readline = require("readline");

const rlInterface = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

// there is a simplified version of util.promisify method
const question = (message) => {
  return new Promise((resolve) => {
    rlInterface.question(message, (data) => {
      resolve(data);
    });
  });
};

function sum(a, b) {
  return a + b;
}

async function main() {
  try {
    const argX = await question("Type value of X: ");
    const argY = await question("Type value of Y: ");
    const result = sum(argX, argY);

    console.log(`Result: ${result}`);

    rlInterface.close();
  } catch (e) {
    console.error(e);
  }
}

main();
```

Don't focus on module *readline*, methods *createInterface* and *question*. It's just a [Node](https://byte.ski/notes/Node) specific code that allows us to take data that the user types in the Terminal. Let's focus on functions *sum* and *main*. The function *main* is just an entry point of our small app.

Alright. Now let's test our app that it works correctly. To run the app use this command (if you already in the same folder as file sum.js there):

```
node sum.js
```

The app is asking you to type the value of parameters **X** and **Y**. Let it be 7 and 2. 

We expected that result will be 9 but the result is disappointed. The app prints:

```
72
```

There is a **bug**. The thing is that the value that function *question* returns have type **string**, not **number** as it expected in function *sum*.

It is a typical problem with [JavaScript](https://byte.ski/notes/JavaScript) type system. I would say, it is a JavaScript trademark. Probably, you could see memes and jokes about this problem.

It's all perfectly fine, but how can we avoid this problem? Of course, you can change function *sum* and do something like this (unary add operator):

```js
function sum(a, b) {
  return +a + +b;
}
```

But don't you think that this looks like a bad solution? It seems like that we try to use a patch to hide a hole in the tearing jacket. Instead of this, we can put on a new jacket that won't have holes (or maybe less than the previous one) - [TypeScript](https://byte.ski/notes/TypeScript).

## The solution

### Installing TypeScript

To install [TypeScript](https://byte.ski/notes/TypeScript) globally on your machine let's use [npm](https://byte.ski/notes/npm):

```
npm install -g typescript
```

Alright. Now we need to check that TypeScript was installed. Type this command in the Terminal:

```
tsc --version
```

It should print you something like this:

```
Version 4.2.4
```

It means that [TypeScript](https://byte.ski/notes/TypeScript) was successfully installed on our machine. What is **tsc** command? It is a **TypeScript compiler**. As mentioned in the [previous post](https://byte.ski/blog/article/how-to-install-or-update-node-by-using-nvm), TypeScript compiler is a tool, or program, that turns the TypeScript code into JavaScript code. We need this feature because we will execute this compiled JavaScript code by [Node](https://byte.ski/notes/Node).

### From JavaScript to TypeScript

Alright. To solve the problem we need to write the same code as before but in TypeScript. Let's change extension of the JavaScript file **sum.js** to TypeScript file extension - **.ts**. Just rename the file from **sum.js** to **sum.ts** and let's see that we will have it in the editor.

We just renamed our file but there are already some changes in the editor (I use [Visual Studio Code](https://byte.ski/notes/Visual-Studio-Code)):


![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/11b6fgy4ppiedf4ytrfn.png) 
 

We have several lines with red underlining which means that there are TypeScript errors. There are also two dashed borders on line 11 - TypeScript warnings. But, why don't we just ignore all this stuff and execute our code? Let's try it.

For executing this file now we must first compile it by TypeScript compiler.

Run this command in the Terminal to compile TypeScript file **sum.ts**:

```
tsc sum.ts
```

Oops! After running this command we will see that our code cannot be compiled because of the errors that were marked in the editor.

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wfd0tx9tbd7azwt6cd02.png)
 

And **there is a thing**. TypeScript won't allow you to compile the code that contains errors. 

### Fixing the code

To compile and execute this file we need to fix the code in the file. Let's see what the errors we have there.

The first four problems are about the same thing. 

```
error TS2468: Cannot find global value 'Promise'.

sum.ts:3:18 - error TS2580: Cannot find name 'require'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.

3 const readline = require("readline");
```

TypeScript tries to understand the types of modules that we use in the code - **readline**. To help TypeScript know the types of the modules we need to install **type definitions**. You will learn about it more in the next posts. For now, let's just say that **type definitions** is a special notation that helps TypeScript to know types of code that were originally written in JavaScript.

Let's install it as TypeScript tells us:

```
npm install --sade-dev @types/node
```

Then, try to compile file **sum.ts** again:

```
tsc sum.ts
```

Great! We don't have any errors and successfully compiled our TypeScript file into JavaScript. You should see that there is a new file called **sum.js** in the same folder as **sum.ts**. No, this is not the file that we created before. This file contains compiled JavaScript code of **sum.ts** file.

If you open this file, well... You may be afraid. There is no our code at all! Don't jump to conclusions. It still the same code as we wrote in **sum.ts** but it transformed into a form that is more understandable for runtime environment (in our case - [Node](https://byte.ski/notes/Node), also it might be [Web browser](https://byte.ski/notes/Web-browser)).

Okay, let's execute our code again. But note that we have to execute *compiled code*, i.e. **sum.js**, not **sum.ts**:

```
node sum.js
```

Let's type new values: 13 and 7. We will see the wrong result, again. 

```
137
```

But you said that we will solve this problem by using TypeScript and we will catch the errors before executing the file! Well, there is another thing of TypeScript that you need to remember. *You wanna help? Help yourself!*. In our case, it means that we have to say to TypeScript where the problem can be.

### Use types to prevent bug

Let's describe our problem in the code. The function *question* returns a value that has a type string. But we don't know about it before executing the file. Because we don't know it we bravely put the values that function *question* returns into a parameter of function **sum**. The function **sum** expected that values will have type *number* and it worked with them as if they were numbers.

So, firstly, we need to say to TypeScript that function *question* returns string type. Let's do it!

To specify what type of value function returns we should write this code:

```ts
const question = (message): string => {
  return new Promise((resolve) => {
    rlInterface.question(message, (data) => {
      resolve(data);
    });
  });
};
```

Hmm. We specified the type of returned value, but TypeScript shows that there is an error:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wibn83wv1tf9jykp0bjl.png)
 

An error sounds like this:

```
Type 'Promise<unknown>' is not assignable to type 'string'.ts(2322)
```

It means that we cannot just specify the type **string** as a type of returned value of function *question* because the function *question* is an asynchronous function and returns Promise.

Alright. To specify the type in this kind of function we just need to specify it like `Promise<your_type>` as TypeScript writes to us in the text of the error.

Let's fix that:

```ts
const question = (message): Promise<string> => {
  return new Promise((resolve) => {
    rlInterface.question(message, (data) => {
      resolve(data);
    });
  });
};
```

Okay. Did we tell TypeScript there might be a problem? Not yet. The next step is to specify the types of parameters of the function *sum*.

To specify types of function's parameters we should write this code:

```ts
function sum(a: number, b: number) {
  return a + b;
}
```

Let's look at the function *main* where functions *question* and *sum* are calling:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pt6dixrpme3z1i0pq5uo.png)
 

**This is it!**. This is the error that helps us to fix the bug with the wrong result that prints in the Terminal. Now, if we would try to compile file **sum.ts** we will see the error.

To run our program in one file use this command:

```
tsc sum.ts && node sum.js
```

We will see:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rynkniadx2gijorg4ypj.png)
 

All we have to do is to write a code that *converts* values from string type to number:

```diff
async function main() {
  try {
    const argX = await question("Type value of X: ");
    const argY = await question("Type value of Y: ");
    + const x = Number(argX);
    + const y = Number(argY);
    - const result = sum(argX, argY);
    + const result = sum(x, y);

    console.log(`Result: ${result}`);

    rlInterface.close();
  } catch (e) {
    console.error(e);
  }
}
```

Let's see the result of executing our program:

![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lva5qnza41z88kthqu5z.png)
 

**Congratulations!** You solve the problem and prevent the bug by using TypeScript!

TypeScript compiler is a very configurable tool. In the next post of the series we deep dive into configuring TypeScript.

***Do you like the material? Please, [subscribe to my email newsletter](https://byte.ski/newsletter) to stay up to date.***

<a href="https://byte.ski/newsletter"><img src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fld1yqfgvgz2dgcpho0x.png" alt="subscribe" /></a>