Aman Mittal 👨‍💻Developer 👉 Nodejs, Reactjs, ReactNative | Tech Blogger with 1M+ views on Medium | My weekly dev newsletter 👉 tinyletter.com/amanhimself

Using TypeScript with Node.js and Express

5 min read 1432

Ease of development is great when you are building a server written in JavaScript using Node.js and Express. What happens when this application server scales or you are working in a team of developers all across the world? TypeScript can help.

In this post, I am not going to talk about whether you should use TypeScript or not. This post describes a beginner-friendly way to set up TypeScript in an Express.js app and understand the basic constraints that come with it.

Prerequisites

To take full advantage of this tutorial, please make sure you have the following installed in your local development environment:

  • Node.js version >= 12.x.x installed
  • Access to one package manager such as npm or yarn
  • Basic knowledge of Node.js and Express

Create a minimal server with Express

Start by creating a new directory where you keep your side projects in your local development environment. Inside that directory, use npm’s initializer command to create a package.json file:

media server
cd server/
npm init --yes

The --yes flag uses the default settings when initializing a package.json from npm config you might have set up.

The package.json file created might look something like this:

{
  "name": "express-ts-example",
  "version": "0.0.1",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "Aman Mittal (https://amanhimself.dev)",
  "license": "MIT"
}

After the initializing step, let us add an express package. From the terminal window, run the command:

yarn add express@4.17.1

Next, create a new file called index.js at the root of the project with the following code to trigger a minimal server:

const express = require('express');
const app = express();
const PORT = 8000;
app.get('/', (req,res) => res.send('Express + TypeScript Server'));
app.listen(PORT, () => {
  console.log(`⚡️[server]: Server is running at https://localhost:${PORT}`);
});

Go back to the terminal and trigger the common node index.js to start the server.

localhost displaying Express + TypeScript server

We made a custom demo for .
No really. Click here to check it out.

The Express server is now up and running.

Add TypeScript

Let’s add two libraries to the development server as devDependencies.

  • typescript is a core library that helps to compile the TypeScript code to valid JavaScript
  • ts-node is a utility library that helps to run a development server written using TypeScript directly from the terminal

To install them, from a terminal window run the following command:

yarn add -D typescript ts-node

The -D flag is also known as --dev flag and is a specification for the package manager to install these libraries as devDependencies.

Once these libraries are installed, go to the package.json file and see a new devDependencies object:

"devDependencies": {
  "ts-node": "8.10.2",
  "typescript": "3.9.5"
}

Next, create a tsconfig.json file at the root of the development server project. This file allows you to customize TypeScript configuration and add other configurations to compile the TypeScript project:

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "rootDir": "./",
    "outDir": "./build",
    "esModuleInterop": true,
    "strict": true
  }
}

The compilerOptions is a mandatory field that needs to be specified. The options used in the config above are:

  • target allows us to specify the target JavaScript version that compiler will output
  • module allows us to use a module manager in the compiled JavaScript code. The commonjs is supported and is a standard in Node.js
  • rootDir is an option that specifies where the TypeScript files are located inside the Node.js project
  • outDir specifies where the output of the compiled is going to be located
  • esModuleInterop allows us to compile ES6 modules to commonjs modules
  • strict is an option that enables strict type-checking options

There might be other configuration options that you can add on for the TypeScript compiler but these are the basic configuration options specified that can help you to get started.

Install declaration files for Node.js and Express

Declaration files are predefined modules that describe the shape of JavaScript values (the types present) for the TypeScript compiler. Type declarations are usually contained in files with a .d.ts extension. These declaration files are available for all libraries that are originally written in JavaScript and not TypeScript.

There is a GitHub repository that maintains the TypeScript type definitions to use directly in Node.js and other JavaScript projects without bothering to define these types from scratch. This repository is called DefinitelyTyped.

To add these types or the declaration files related to a particular library or a module, you have to look for the packages that start with @types namespace.

For example, the type definitions for Express library is kept under a specific package called @types/express. For using a utility library such as bodyParser (which is a middleware to parse an incoming request’s body), there is a specific type of definition module called @types/body-parser.

To install type definitions for Node.js and Express, run the below command. Do note that, these type definitions are installed as devDependencie:

yarn add -D @types/node @types/express

Notice the versions of these packages installed in package.json file:

"devDependencies": {
    "@types/express": "4.17.6",
    "@types/node": "14.0.13",
    "ts-node": "8.10.2",
    "typescript": "3.9.5"
}

Create an Express server with .ts extension

Now you can easily convert the minimal server code in index.js to index.ts file. That is the first step. Rename the file to index.ts.

The .ts extension is a file extension to determine the TypeScript files that are compiled to JavaScript files later when building the server.

Open index.ts file. You can now use the import statements from ES6. The only required package right now in the index.ts file is express. Replace it with the following statement:

import express from 'express';
// rest of the code remains same
const app = express();
const PORT = 8000;
app.get('/', (req, res) => res.send('Express + TypeScript Server'));
app.listen(PORT, () => {
  console.log(`⚡️[server]: Server is running at https://localhost:${PORT}`);
});

The TypeScript compiler will handle the conversion of import statements to require statements.

Watching file changes with nodemon

Another development related utility library I like to use when working on Node.js projects is nodemon. Let’s install this using the command below:

yarn add -D nodemon

nodemon is a tool that helps develop Node.js based applications by automatically restarting the Node application when file changes in the directory are detected. To use it, you may add a start script in the package.json file as specified below:

"scripts": {
    "start": "nodemon index.ts",
},

Now, go back to the terminal window, and run yarn start or npm start.

nodemon index

Since there are no errors, the server is successfully running. You can go to the browser window to see the result.

Since nodemon detected changes, let’s try to edit the message sent from res.send() and simultaneously take a look at the terminal to see if nodemon detects any file changes or not.

using nodemon to detect changes in the file

The ts-node utility checks for any file changes in the current TypeScript project. If there is a TypeScript error, this module will let the nodemon crash the server and instead display that error.

Compile a TypeScript project

To compile a TypeScript project to a valid JavaScript one, start by declaring a new script called build inside the package.json file:

"scripts": {
    "build": "tsc --project ./",
},

TypeScript provides a command to compile the code called tsc. This command demands a flag to specify as to what to compile. The --project (shorthand: -p) is used to specify the project directory that the compiler can pick the code files from to compile to valid JavaScript. The ./ specifies the root project.

From the terminal window, run the build command to compile the code:

yarn run build

expresstsexample

There is a new build directory created after this command executes successfully. Inside this directory, there is the TypeScript code compiled to valid JavaScript:

'use strict';
var __importDefault =
  (this && this.__importDefault) ||
  function(mod) {
    return mod && mod.__esModule ? mod : { default: mod };
  };
Object.defineProperty(exports, '__esModule', { value: true });
const express_1 = __importDefault(require('express'));
const app = express_1.default();
const PORT = 8000;
app.get('/', (req, res) =>
  res.send('Express + TypeScript Server is awesome!!!')
);
app.listen(PORT, () => {
  console.log(`⚡️[server]: Server is running at https://localhost:${PORT}`);
});

If you specify any other directory named as the value of the property outDir in the tsconfig.json file that name of the directory would have reflected here instead of build.

Conclusion

Using TypeScript has its benefits but it does come with a bit of a learning curve. You have to carefully analyze whether using TypeScript in your Node.js and Express.js backend projects is beneficial or not. This may depend on the requirements you have. Make sure to check out the different Typed Definitions or go to the official TypeScript documentation to explore more.

You come here a lot! We hope you enjoy the LogRocket blog. Could you fill out a survey about what you want us to write about?

    Which of these topics are you most interested in?
    ReactVueAngularNew frameworks
    Do you spend a lot of time reproducing errors in your apps?
    YesNo
    Which, if any, do you think would help you reproduce errors more effectively?
    A solution to see exactly what a user did to trigger an errorProactive monitoring which automatically surfaces issuesHaving a support team triage issues more efficiently
    Thanks! Interested to hear how LogRocket can improve your bug fixing processes? Leave your email:

    200’s only Monitor failed and slow network requests in production

    Deploying a Node-based web app or website is the easy part. Making sure your Node instance continues to serve resources to your app is where things get tougher. If you’re interested in ensuring requests to the backend or third party services are successful, try LogRocket. https://logrocket.com/signup/

    LogRocket is like a DVR for web apps, recording literally everything that happens on your site. Instead of guessing why problems happen, you can aggregate and report on problematic network requests to quickly understand the root cause.

    LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. .
    Aman Mittal 👨‍💻Developer 👉 Nodejs, Reactjs, ReactNative | Tech Blogger with 1M+ views on Medium | My weekly dev newsletter 👉 tinyletter.com/amanhimself

    3 Replies to “Using TypeScript with Node.js and Express”

    Leave a Reply