# How to Convert Express.js to Typescript

> Looking for how to fix `parameter 'req' implicitly has an 'any' type`? (or something similar) 
> [Read This!](https://blog.phillipninan.com/types-in-typescript#what-are-the-downsides-of-using-types)

In my previous article, we learned how to [get started with Express.js in 5 minutes](https://pninan.hashnode.dev/getting-started-with-expressjs-in-5-minutes). Today, I am going to show you how to convert a JavaScript [Express.js](https://expressjs.com/) project to [TypeScript](https://www.typescriptlang.org/).

If you enjoy this article give me a follow on [Twitter](https://twitter.com/ninan_phillip) to read all of my latest software development content!

## Pro Tip
> 
3 Reasons to Use TypeScript.
- TypeScript is much easier to read and debug.
- TypeScript makes you much more productive with the help of IDE's such as VS Code
- If you know JavaScript you already know TypeScript!

**TLDR:** Here is the fulling working code on my [Github](https://github.com/fourgates/blog-express-ts-docker/tree/part-2-typescript).

## Install & Configure TypeScript
Let's get started. Please refer to my [previous post](https://pninan.hashnode.dev/getting-started-with-expressjs-in-5-minutes) as a starting point for this article. First, you will need to install the TypeScript compiler via `npm`.
```
npm install --save-dev typescript
```

Next, we need to add a file to tell TypeScript how to compile (transcompile) your TypeScript code into native JavaScript. This is needed because JavaScript environments (browsers) only understand... well, JavaScript. Let's add a `tsconfig.json` file to the root of the project.
```
nano tsconfig.json
```

```
{
    "compilerOptions": {
        "module": "commonjs",
        "esModuleInterop": true,
        "target": "es6",
        "noImplicitAny": true,
        "moduleResolution": "node",
        "sourceMap": true,
        "outDir": "dist",
        "baseUrl": ".",
        "paths": {
            "*": [
                "node_modules/*"
            ]
        }
    },
    "include": [
        "src/**/*"
    ]
}
```

A couple of notes on this configuration:
- `module` - We are using `commonjs` here. This is the module system that Node.js uses.
- `target` - We are targeting the ES6(ES2015) standard which is compatible with modern versions of Node.js.
- `include` - The TypeScript compiler will try to compile any TypeScript files ending in `.ts` it finds in the `src`.
- `outDir` - The folder where compiled JavaScript gets saved, in this case, `dist`. This is a common folder name for this use case.

## Install & Configure TSLint
Now we are going to install a linting tool. This is a static code analysis instrument used to find problems in your code while you write it. Also, it can be used to keep styles (tabs/indentations) consistent in a project. We will be using [TSLint](https://github.com/palantir/tslint) for this demo.

First, we need to install `tslint` as a dev dependency. This means that it is only used when you are writing code. It will not be included when you build the project for production deployment. This yields smaller builds with fewer security concerns. 
```
npm install --save-dev tslint
```

Next, we will create a `tslint.json` file to instruct `tslint` how to `lint` our project.
```
nano tslint.json
```
```
{
    "defaultSeverity": "error",
    "extends": [
        "tslint:recommended"
    ],
    "jsRules": {},
    "rules": {
        "trailing-comma": [ false ]
    },
    "rulesDirectory": []
}
```
A couple of notes on this configuration:
- `defaultSeverity` - This is the default severity level applied to the configured rules. 
- `extends` - We are going to extend the recommended `tslint` rules.
- `rules` - We are adding a custom rule here to not allow trailing commas. 

## Update NPM Configuration
Now that we have TypeScript and TSLint installed and configured, we need to update `package.json` to tell node how to build the project with TypeScript. 
```
nano package.json
```

```
 "main": "dist/index.js",
  "scripts": {
    "prebuild": "tslint -c tslint.json -p tsconfig.json --fix",
    "build": "tsc",
    "prestart": "npm run build",
    "start": "node .",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
```
A couple of notes on the changes:
- `main` - This now points to the compiled JavaScript file inside of the `dist` folder
- `prebuild` - Before we build the project we are going to `lint` the project. 
- `-c` - This passes a configuration file to `tslint`
- `-p` - This passes a TypeScript config file to `tslint`
- `--fix` - This flag is used to fix linting errors for the selected rules, this may overwrite linted files
- `build` - The `tsc` command will compile your project. If you want to compile your JavaScript files without starting the project you can run `npm run build`

Lastly, we need to change our single JavaScript file to TypeScript! You simply need to change the file from `.js` to `.ts`.
```
cd src
mv index.js index.ts
```

## Start your servers!
Time to start our new TypeScript project!

```
cd ..
npm run start
```

Oh no! The project no longer compiles!
```
ERROR: 1:17  no-var-requires  require statement not part of an import statement
ERROR: 12:4  no-console       Calls to 'console.log' are not allowed.
ERROR: 6:17 - error TS7006: Parameter 'req' implicitly has an 'any' type.
ERROR: 6:22 - error TS7006: Parameter 'res' implicitly has an 'any' type.
```

There are three main issues we need to address with the original code we wrote. TSLint does not consider using `console.log` production-ready code. Therefore, we will need to add some syntactical sugar to tell TSLint to ignore this error.
```
app.listen( port, () => {
    // tslint:disable-next-line:no-console
    console.log( `server started at http://localhost:${ port }` );
} );
```

Second, when using TypeScript you should use `import` instead of `require`. Therefore, we just need to change a line of code from:
```
const express = require( "express" );
```
to
```
import express from "express";
```

Third, the TSLint also does not like using the `any` parameter type. If you do not declare a type for a parameter it is implicitly `any`. It's a best practice to use `types`, it is called TypeScript! A simple fix for this is to add some well-known type declaration files for node and express. Since we are using the express library any callback functions should have types associated with them.
```
npm install --save-dev @types/node @types/express

```

## Start your servers! (Take 2)

Finally, start up your project and you should be good to go this time around!
```
npm run start
```

## Conclusion 
It is very straightforward to get started with TypeScript, and I highly recommend it. You will be able to take advantage of tools that make you more efficient and will produce fewer errors, a win-win! Here is the fulling working code on my [Github](https://github.com/fourgates/blog-express-ts-docker/tree/part-2-typescript)

## Caveats
TSLint is currently deprecated. I purposely used it here so I can write a future post on how to migrate TSLint to ESLint. Keep an eye out for the updated post! I will add a link in the future. 


## Resources
[Use TypeScript to Build a Node API with Express](https://developer.okta.com/blog/2018/11/15/node-express-typescript)

[What Is Typescript and Why Use It](https://dzone.com/articles/what-is-typescript-and-why-use-it)

[Javascript Transpilers -- What They Are Why We Need Them](https://scotch.io/tutorials/javascript-transpilers-what-they-are-why-we-need-them)

[TSlint Usage](https://github.com/palantir/tslint#installation--usage)


