How to Set up Basic Node.js + Express.js Server with TypeScript

Note: This post is part of Learn How to Use TypeScript With Node.js and Express.js series. Click here to see the first post of the series.

Getting Started

First things first, we need to create the directory for our application:

mkdir express-typescript

Time to set up our package.json file where we can define all our dependencies as well as executable scripts.

npm init

Once this script is run, it will ask you the following questions:

package name: (src) express-typescript
version: (1.0.0)
description:
entry point: index.ts
test command:
git repository:
keywords:
author:
license: (ISC)

Feel free to provide the correct details. For now, the only information we cared to provide is the package name and the entry point set to index.ts.

Installing Dependencies

Since we are going to work with Express.js, we need to install Express.

npm i --save express

We need to install TypeScript as well as Express types to take advantage of TypeScript, but in this case, we will install them as part of the dev dependencies.

npm i --save-dev typescript @types/express

So far, this is how your package.json should look like:

{
  "name": "express-typescript",
  "version": "1.0.0",
  "description": "RESTful API Example of using Express with Typescript",
  "main": "index.ts",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Andrés Reales",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1"
  },
  "devDependencies": {
    "@types/express": "^4.17.11",
    "typescript": "^4.2.4"
  }
}

Create Minimal Server with Express.js and TypeScript

Let’s create what could be considered the most basic server using Express.js. Inside the src folder, create an index.ts file and copy the following code:


import express, { Request, Response } from 'express';

const app = express();
const port = 3000;

app.get('/', (req: Request, res: Response) => {
  res.send('Hello World!');
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`)
});

As you notice, it will be a simple GET API endpoint returning a message.

Running TypeScript Files in Node.js: Understanding the Process

First, it is important for you to understand the process that happens to run TypeScript files in node.js. Previously, you created a simple server inside the index.ts. If we were working with plain JavaScript, a similar code could be written in a js file such as index.js. Normally, you will run a js file using the node command.

node src/index.js

If we try to do something similar with index.ts file, the terminal will fail due to syntax errors as we are writing code in TypeScript.

// it will fail
node src/index.ts

What we need to do is to compile our TypeScript code into JavaScript code, and we are going to do that using the tsc command which it is available after installing typescript dependency in the project.

npx tsc src/index.ts

This will generate an index.js file. Now that we have our JavaScript file, we can use node to run our code.

node src/index.js

This will run our server in port 3000. Try opening your browser http://localhost:3000/. You should see a Hello World! message.

We could also set up a tsconfig.json file. This file is used to determine what all TypeScript files will be compiled in a project. This is useful especially when you want to avoid compiling files containing unit or integration tests. Feel free to checkout for more information about the compilation options available in TypeScript.

Running TypeScript Files in Node.js: Quick Process

There is a package available called ts-node which allows executing our TypeScript file in node. Therefore, we are going to install ts-node as part of our development dependencies.

npm i --save-dev ts-node

Once the package is installed, we can run our project with only one command.

npx ts-node src/index.ts

The best thing is that you don’t see any index.js file generated.

Why using npx to run ts-node?

At the moment you installed npm, it came with npx. This makes it so we have a command to manage dependencies, and another one to execute dependencies.

  • npm (package manager)
  • npx (package eXecutable)

This gives us the opportunity to execute local dependency files, such as, ts-node.

If we were to install ts-node globally like this:

npm i -g ts-node

We could directly execute the ts-node command.

ts-node src/index.ts

However, this can be problematic especially when working with specific versions of dependencies. The npx command is also useful when looking to run packages only once and delete them once they are executed. For example, if you try to create a react application using create-react-app, React’s tutorial recommends using the npx command.

Setting Up Scripts in the package.json

Now that we understand how to run TypeScript files, we can set up a couple of scripts in the package.json for our application. We are going to start by setting the start script in the package.json file.



"scripts": {
    "start": "npx ts-node src/index.ts",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

Once we save, we can open the terminal and run npm run start and you will notice our project is running again.

However, we constantly make changes during the development phase, and it turns time-consuming to stop and re-run the project after every change we make to the code base. We are going to install nodemon.

npm i --save-dev nodemon

Now we can set up another script such as start:watch to run nodemon.

"scripts": {
    "start:watch": "nodemon src/index.ts",
    "start": "npx ts-node src/index.ts",
    "test": "echo \"Error: no test specified\" && exit 1"
  },

Prior to running npm run start:watch we need to add an additional configuration. Let’s create another file called nodemon.json in the root of the project, not inside the src folder. Once created, assign the following configuration.

{
  "watch": "src/**/*.ts",
  "execMap": {
    "ts": "ts-node"
  }
}

This file is the configuration setup at the moment of executing nodemon. In this case, it will execute ts-node for any .ts file that is executed using nodemon.

Now it is time to try our script.

npm run start:watch

You should see your application running. Try making changes to the index.ts file such as modifying the log generated inside the callback of the listen function.

console.log(`I just changed this log: http://localhost:${port}`)

Once you save, you should see the updated log in the terminal.

This is the final value for our package.json of our project.

{
  "name": "express-typescript",
  "version": "1.0.0",
  "description": "Example of using Express with Typescript",
  "main": "index.ts",
  "scripts": {
    "start": "npx ts-node src/index.ts",
    "start:watch": "nodemon src/index.ts",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "Andrés Reales",
  "license": "ISC",
  "devDependencies": {
    "@types/express": "^4.17.11",
    "nodemon": "^2.0.7",
    "ts-node": "^9.1.1",
    "typescript": "^4.2.4"
  },
  "dependencies": {
    "express": "^4.17.1"
  }
}

Setup TypeScript Configuration

The tsconfig.json file specifies the root files and the compiler options required to compile a TypeScript project. Without it, our TypeScript project would still feel as a JavaScript project because it we are not enforcing the usage of types in our codebase. Therefore, we are going to create a tsconfig.json in the root folder of our project. Once this is done, add the following configuration:

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

Later on, you can make changes to the configuration based on your project needs. For now, this is a good starting point.

What’s Next?

That’s all for this article, and I’m sure you want to get going with more. In the next section, I will explain How to Set up RESTful API Routing using Express.js with TypeScript.