How to Debug Node.js with TypeScript using Nodemon?

TypeScript has become an excellent alternative to prevent data type definition issues often found when working with JavaScript. Companies are migrating to TypeScript as the default programming language for their Node.js backend. However, developers struggle to set up local debugging configurations when using nodemon. In this article, you will learn how to fix that issue.

Note: It is important to mention, the solutions presented in this article work if you are using ts-node to run TypeScript in Node.js.

Prior to using Typescript in Node.js, we could plug in a script configuration similar to the following in our package.json:


{
  "name": "debug-typescript-node",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start:watch:inspect": "nodemon --inspect index.js"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "nodemon": "^2.0.12",
    "ts-node": "^10.2.1",
    "typescript": "^4.4.2"
  }
}

However, attempting to do a similar approach but using the ts-node package to transform the TypeScript code into JavaScript and execute it in Node.js won’t work.

For example, a workable script that doesn’t debug would look like the following:


{
  "scripts": {
    "start:watch": "nodemon -e ts --exec \"ts-node index.ts\""
  }
}

Trying to add the –inspect in the script in hopes attach the debugger to a port like the following won’t work:


{
  "name": "debug-typescript-node-nodemon",
  "version": "1.0.0",
  "description": "",
  "main": "index.ts",
  "scripts": {
    "start:inspect": "nodemon --inspect --exec 'ts-node' src/index.ts"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "nodemon": "^2.0.12",
    "ts-node": "^10.2.1",
    "typescript": "^4.4.2"
  }
}

This can quickly become a motive of frustration as coding without having the ability to debug can slow the development process. The following are a couple of solutions I have personally tested.

Solution: Scripts with nodemon local configuration (Preferred)

Nodemon allows you to set up local and global configurations, which usually are located in a file named nodemon.json.

  1. Create nodemon.json file within the home directory.
  2. Add the following configuration in the nodemon.json file.
    {
      "execMap": { 
        "ts": "node --require ts-node/register"
      }
    }
    
  3. Update the script in the package.json file. In this case, the start:inspect script.
    
    {
      "name": "debug-typescript-node-nodemon",
      "version": "1.0.0",
      "description": "",
      "main": "index.ts",
      "scripts": {
        "start:inspect": "nodemon --inspect index.ts"
      },
      "author": "",
      "license": "ISC",
      "devDependencies": {
        "nodemon": "^2.0.12",
        "ts-node": "^10.2.1",
        "typescript": "^4.4.2"
      }
    }
    

Solution: Scripts without nodemon local configuration

For those who don’t want to generate more files in the project, nodemon allows you to run specific configurations without the need for a local configuration or a nodemon.json file. In this case, the script should look like the following:


{
  "name": "debug-typescript-node-nodemon",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start:inspect": "nodemon --exec \"node --require ts-node/register --inspect index.ts\""
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "nodemon": "^2.0.12",
    "ts-node": "^9.1.1",
    "typescript": "^4.4.2"
  }
}


Changing Debugger Ports

When using the –inspect flag, the debugger will listen to port 9229 by default. You should see a log in the terminal along the following lines:

Debugger listening on ws://127.0.0.1:9229/3af7812e-8cb5-4ab8-81a1-710801f5c25d

If you are working on several different projects and you want to enable debugging configuration in each of them without stopping the debugger from one project because port 9229 is in use, we can specify the debugger port to use.


{
  "name": "debug-typescript-node-nodemon",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start:inspect": "nodemon --exec \"node --require ts-node/register --inspect=1234 index.ts\""
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "nodemon": "^2.0.12",
    "ts-node": "^9.1.1",
    "typescript": "^4.4.2"
  }
}

In the previous example, the debugger will be listening to port 1234. Feel free to use any other available port.

Visual Studio Code launch.js Configuration

Is VS Code your favorite IDE? Nowadays, VS Code has become the first IDE of choice by many developers and it is important to take advantage of all of its features, such as debugging features.

If we were to have the following scripts in our package.json:


{
  "scripts": {
    "start:inspect": "nodemon --exec \"node --require ts-node/register --inspect index.ts\""
  }
}

We could have the following launch.js configuration to launch the application and immediately attach the debugger or to attach the debugger whenever we wish to debug some code.


{
  // Use IntelliSense to learn about possible attributes.
  // Hover to view descriptions of existing attributes.
  // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Nodemon: Launch Express.js + TypeScript",
      "type": "node",
      "request": "launch",
      "runtimeExecutable": "npm",
      // run start:inspect script set in package.json
      // it is like vs code running npm run start:inspect
      "runtimeArgs": [
        "run-script",
        "start:inspect"
      ],
      "sourceMaps": true,
      // VS Code default debug port is 9229. Feel free to change it you are
      // running mulitple applications in different VS Code windows
      "port": 9229,
    },
    {
      "name": "Nodemon: Attach Express.js + TypeScript",
      "type": "node",
      "request": "attach",
      // VS Code default debug port is 9229. Feel free to change it you are
      // running mulitple applications in different VS Code windows. If you
      // want to change the port, make sure to update the script, i.e.,
      // "start:inspect": "nodemon --inspect=1234 src/index.ts",
      "port": 9229,
      // If you make changes to your code and save changes, nodemon will
      // automatically restart your server. In a similar way, you can restart
      // the debugger. If "restart" is set to false, then every time you save
      // new changes to your code while running nodemon, you will need
      // to re-run the debugger
      "restart": true,
      "protocol": "inspector"
    }
  ]
}

Hope these solutions help you set up your debugger configuration when developing Node.js with TypeScript applications using nodemon.

If you have any issues, don’t hesitate to ask questions.