How to Convert Express.js to Typescript

How to Convert Express.js to Typescript

Looking for how to fix parameter 'req' implicitly has an 'any' type? (or something similar) Read This!

In my previous article, we learned how to get started with Express.js in 5 minutes. Today, I am going to show you how to convert a JavaScript Express.js project to TypeScript.

If you enjoy this article give me a follow on Twitter 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.

Install & Configure TypeScript

Let's get started. Please refer to my previous post 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 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

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

What Is Typescript and Why Use It

Javascript Transpilers -- What They Are Why We Need Them

TSlint Usage

Did you find this article valuable?

Support Phillip Ninan by becoming a sponsor. Any amount is appreciated!