loading...
Cover image for How to Debug Nodejs, TypeScript Code in VSCode

How to Debug Nodejs, TypeScript Code in VSCode

macmacky profile image Mark A Updated on ・4 min read

Hi Guys Good Day!

It's been almost two years since I've been using TypeScript in my projects. One of the problems that I was having when starting using TypeScript in VSCode was how to debug it. Yea, TypeScript compiles to plain old JavaScript, we could debug the output JavaScript code but I don't want to do that and also the JavaScript output code is old but not that old it depends on your configuration. So, I wanna show you how to debug TypeScript code with VSCode.

And also I wanna mention, TypeScript is one of the most popular programming languages right now. Check out these links.

State of JS - JavaScript Flavors
Stack Overflow Survey - 2019
RedMonk - Most Programming Languages - January 2020

So, Let's start coding.

First, you need to have Node.js and VSCode installed on your computer and TypeScript. The links are down below.

Node.js
VSCode

To install TypeScript, run this command after installing Nodejs.

npm i -g typescript

After installing TypeScript globally, from your desktop run these commands.

 md typescript-debug && cd typescript-debug && code .

Basically what this means is that we are making a directory (md) that has a name of typescript-debug and changing our current directory (cd) Desktop to typescript-debug and opening the VSCode in the typescript-debug directory with the (code .) command.

Inside the directory, run these commands.

 npm init --y && tsc --init

What these commands mean is that where initializing a Node project and using the default configuration(npm init --y) and we're gonna use TypeScript in this project (tsc --init).

And lastly, (bear with me) we're gonna install express and the type definitions for express module using these commands.

  npm i -P express && npm i -D @types/express

npm i is alias for npm install. -P means that the package is a Dependency in our project and -D means that the package is a Development Dependency in our project.

Our package.json file.

{
  "name": "typescript-debug",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "dependencies": {
    "express": "^4.17.1"
  },
  "devDependencies": {},
  "scripts": {
    "start": "tsc"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Our tsconfig.json file.

{
  "compilerOptions": {
    "target": "es5",
    "lib": [
      "ES2015",
      "DOM"
    ],
    "sourceMap": true,
    "outDir": "./build",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "noEmitOnError": true,
    "watch": true
  },
  "exclude": [
    "node_modules"
  ]
}

Ok, I'm gonna explain the most important parts in the tsconfig.json config.

exclude - The files or directories that we don't want to be compiled. In this example, we don't want the typescripts files inside the node_modules folder to be compiled to javascript.

target - The target version of our javascript output code.

lib - This is a list of the helper libraries that we're gonna use in our typescript code and also in the compilation.

sourceMap - A boolean indicating if we want a source map file for each typescript file.

outDir - The path or folder name to our javascript output code.

rootDir - The root directory for our typescript files.

strict - A boolean indicating if we want strict checking in our typescript code.

esModuleInterop - This option needs a lot more explanation. So, I'm gonna just give you an example. This is a boolean value.

If we set this to false. Our import statement would like this.

import * as express from 'express';

If we set this to true. Our import statement would like this.

import express from 'express';

For more details, read this.

noEmitOnError - A boolean indicating if an error occurred in type checking
will not emit or compile javascript code.

watch - A boolean indicating that we run the compiler in watch mode. If any files change in our rootDir, it will compile new files automatically.

Our launch.json file inside the .vscode folder.

{
    // 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": [
        {
            "type": "node",
            "request": "launch",
            "name": "Launch Program",
            "program": "${workspaceFolder}/src/app.ts",
            "sourceMaps": true,
            "trace": "all",
            "outFiles": [
                "${workspaceFolder}/build/**/*.js"
            ]
        }
    ]
}

And lastly, the app.ts file inside the src folder.

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

const app: express.Application = express();
const port: number = 3000;


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


app.get('/:name', (req: Request, res: Response) => {
    res.send(`Hello ${req.param('name', 'Mark')}`);
});


app.listen(port, () => {
    console.log(`Server listening at port: ${port}`);
});

Before starting the debug server, place breakpoints anywhere in the app.ts file and run the npm start command to start the TypeScript Compilation Server and then press F5 and open your browser and navigate to http://localhost:3000 or http://localhost:3000/anna. And, if it's working and it passes your breakpoints then great but if not then maybe there's something with your configurations, please follow the instructions above and retrace the things that you missed.

By the way, I haven't mentioned the most important thing that allows us to debug our TypeScript code. It's Source Maps. Most of our code (JS/CSS) in production are combined and minified so that we can dramatically reduce the size of our assets and also reduce the number of files in production to improve the load time performance of a website. But debugging in a minified code is hard, sorry "hard" is a soft word for this, it's impossible. This is where Source Maps comes into play. Basically, a Source map is a file that maps the minified/transformed source to the original source. This helps us, developers, a lot because we can debug that minified code with the original code. Source maps are awesome.

Thanks guys for reading this post.

Have a Nice Day 😃!.

Posted on by:

macmacky profile

Mark A

@macmacky

a Full-Stack developer who likes reading Tom Clancy's books and loves talking with dogs.

Discussion

pic
Editor guide
 

I find it much easier to use ts-node and you never have to run the compile task. You can just debug the ts files directly. Check out the launch configs in this repo: github.com/jdforsythe/bloch

 

Thank you for sharing, it's very helpfull

 

Thanks! I'm glad that it helped you.

 

launch.json
MINER_PRIV_KEY

I hope these are temporary keys

 

It's not a real (or secure) network! It was an example for demonstrating blockchain concepts and TypeScript during a presentation I gave to a local college. You can see the slides in the repo, as well.

 

Thank you for this info man! Much appreciated.

 

Configuring TypeScript is complicated. Making it work seamlessly with Jest, and various tools that need its source map is even more complicated.

We recently released a boilerplate for quick getting started with a production-grade project featuring the Next.js framework, hosted on Zeit platform at github.com/UnlyEd/next-right-now. It has full TS support.

It can be used as a boilerplate, but many of you may find it interesting as a learning resource as well. It's very well documented!