My TypeScript + NodeJS + Express setup for maximum productivity

Ionut Ciobanu (John)
5 min readFeb 1, 2021

Introduction

Hello! This guide is dedicated to both new and experienced developers who would like to setup their workflow in developing backend APIs in NodeJS using TypeScript and Express (or anything you would like).

You can use this guide as an exact template or extract only the steps that interest you. After working for about 3 years and trying different styles and workflows, this is what I’ve found fitting my style the best and helping me be more productive.

TL;DR;
You can use nodemon with tsc -w to automatically build your typescript code as you write. Run the following scripts in separate terminals:

"scrips": {
"buildAndWatch": "tsc -w -p tsconfig.json",
"startAndWatch": "nodemon ./dist/index.js"
}

What you will need

First you’ll have to install NodeJS (https://nodejs.org/en/download/) if you don’t have it already. The version is not important, but a more recent one is preferable.
We’ll install the rest of dependencies together in the next section.

Summary

  1. Project setup | Quick initialization and dependencies installation
  2. Workflow and scripts| Automate work by letting the scripts do it for you

Project Setup

I’m going to create a new project from scratch, but you can apply the same dependencies if they are not installed to your existing project.
Since I’m using VS Code I’ll just create a new folder and open VS Code there.

Project initialization

Open the terminal and navigate to your project directory
Pro Tip: You can use CTRL + ` (or Command + ` on Mac) in VS Code to toggle the terminal or go to View -> Terminal

First, create your project’s package.json — this is where all your dependencies information are saved like type (dependencies, dev dependencies or optional dependencies), name (express, typescript, nodemon) and version (2.2.5, 16.4.2). To create it just run:

npm init -y

The -y flag is optional. But what does it do? It basically uses defaults values for all the fields. You can omit it and input the name, version and all that in an interactive manner, but I just prefer to update it manually later.

Output of running the npm init -y command

The name of the project is recommended to be lower case inside package.json. Also the “main” might need to be updated depending on what is the name of the build folder. I usually do build/index.js

Installing dependencies

With the terminal still open, it’s time to install our dependencies.
I usually install Typescript and Nodemon as global packages since I’m using them on most of the projects.

npm install -g typescript nodemon 

What is nodemon? It stands for Node Monitor (not “no demon”, as I first thought). Basically it will run a Node process and a watcher on your project files. If the files changes (e.g. when you write something) the process is restarted, so you don’t have to kill the current instance and run a new one.

Initialize your tsconfig.json using if don’t have already

tsc --init

You can configure it the way you like. For the propuse of this tutorial I’ll just modify “outDir” to be “./dist”

Let’s now install express and the typings

npm install --save expressnpm install --save-dev @types/express @types/node

Workflow and scripts

First, let’s create a server with a simple route that serves some data.
Create index.ts:

import express, { Application, Request, Response } from 'express' const app: Application = express();app.use(express.json());
app.use(express.urlencoded({ extended: false }));
// Other configurations like using helmet, setting up routesapp.get('/api/demo', (request: Request, response: Response) =>
{
response.json({ fancyJson: 'Goes here' });
});
app.listen(() => console.log('Server started at http://localhost:3000/ ...')

Normally to transpile and run the server you would write:

tsc -p tsconfig.json
node ./dist/index.js

What I’ve seen most people do is creating a script to do this automatically

"scrips": {
"buildAndRun": "tsc -p tsconfig.json && node ./dist/index.js"
}

My problem with this approach is that I was spending a lot of time pressing “Ctrl + C” to kill the current process and then press up arrow to run the script again. But what if this could be done automatically?

Well, you can. Tsc has a flag “-w” which stands for “watch”. This will automatically transpile your typescript code into javascript as soon as you save.
Pro Tip: You can go to settings and enable “save: afterDelay” or on focus change, and “format on save” to keep the code pretty. I will create a tutorial on how I like to setup my code to be formatted.
I usually create these two scripts:

"scrips": {
"buildAndWatch": "tsc -w -p tsconfig.json",
"startAndWatch": "nodemon ./dist/index.js"
}

First, I run “buildAndWatch”

npm run buildAndWatch

Then I click on the + in VS Code to open a new terminal

And run the second script

npm run startAndWatch

You could also merge these two scripts into one by using the | operator to run them in parallel, but you would lose the output in the terminal.

Using this approach you can jump between terminals and see the output, typescript for transpiling errors, Nodemon for logs and output.

Now you can call your route at: http://localhost:3000/api/demo
Make a change to your code
Make another call and see the changes applied.

I would also use ESLint with the plugin for typescript and have the code checked at build time and use VSCode extension for ESLint.

If you’ve read until here I’d like to thank you and hope that I could help you save a little bit of time and frustration :)

--

--

Ionut Ciobanu (John)

I’m a software and game developer passionate about clean code, architecture, cars and efficiency.