Skip to Content
Course content

56: Debugging TypeScript with Source Maps

Click on the "Edit" button in the top corner of the screen to edit your slide content.

You’ve probably noticed by now that browsers and Node.js have no idea what a .ts file is. They only speak JavaScript. This means that whenever we run our code, we're actually executing the compiled output. For a while, that's fine. But the moment you hit a runtime error, the browser's console points you to a line number in a .js file that looks nothing like the code you actually wrote.

That's where source maps come in. Think of a source map as a dictionary that tells the debugger, "Line 12, Column 4 of app.js actually corresponds to Line 5, Column 2 of app.ts."

Creating a buggy validator

Let's build a small user profile validator. I want to make sure users have a valid age and a non-empty username. I'll intentionally leave a logic bug in here so we have something to actually debug.

// userValidator.ts
interface User {
    username: string;
    age: number;
}

export function validateUser(user: User) {
    console.log("Validating user:", user.username);
    
    if (user.username.length === 0) {
        throw new Error("Username cannot be empty");
    }

    // Logic bug: I accidentally used '>' instead of '<' 
    // and I'm accessing a property that might be undefined
    if (user.age > 150) { 
        console.log("That's a very old user!");
    }

    return true;
}

const testUser = { username: "dev_mentor", age: -5 }; 
validateUser(testUser);

The frustration of debugging compiled JS

If I compile this with a basic tsc command and run it in a browser or Node, and then I look at the stack trace when it crashes (or when I set a breakpoint), I'm staring at the .js file. If I'm using a minifier or a bundler, it's even worse—I'm debugging a single line of mangled code like function a(b){return b.u.length...}. It's a nightmare.

Bridging the gap with sourceMap: true

To fix this, we need to tell the TypeScript compiler to generate these map files. I'll head over to my tsconfig.json and flip the switch.

{
    "compilerOptions": {
        "target": "ES6",
        "module": "CommonJS",
        "sourceMap": true, // This is the magic line
        "outDir": "./dist"
    }
}

Now, when I run tsc, I'll notice that for every .js file in my dist folder, there's a corresponding .js.map file. These are the "dictionaries" I mentioned earlier.

Wait, why isn't it working?

Here is where I usually trip up when I'm setting up a new project. I ran the compiler, I saw the .map files, but when I opened Chrome DevTools, I still saw the JavaScript file. I spent five minutes wondering if my tsconfig was being ignored.

The mistake? I had "Enable JavaScript source maps" unchecked in my browser's DevTools settings. It's a small toggle, but it's the difference between the browser ignoring the map files or actually using them to reconstruct the original TypeScript source in the "Sources" tab. Always check your environment settings before you start blaming the compiler!

Finally seeing the TypeScript source

With the settings corrected, the experience changes completely. I can now open the "Sources" tab in the browser, find userValidator.ts (the actual TypeScript file!), and click on line 15 to set a breakpoint.

When the code hits that breakpoint, the debugger pauses on the TypeScript line. I can hover over the user object and see that age is -5. Because I'm looking at the source map, I can immediately see that my check if (user.age > 150) is useless for catching negative numbers. I can fix the logic in my .ts file, recompile, and I'm back in business without ever having to manually hunt through a compiled JavaScript file.




📋 Practical Task

Fixing the Shopping Cart Totalizer

You have been given a small project with a bug in the price calculation logic. The project is already configured to generate source maps, but the logic is failing in production.

Your Task:

  1. Open the project and run the build command to generate the /dist folder.
  2. Launch the application in your browser and open the Developer Tools.
  3. Navigate to the "Sources" tab and locate the TypeScript file cartLogic.ts (do not debug the .js file).
  4. Set a breakpoint inside the calculateTotal function.
  5. Refresh the page and inspect the item object to find why the total is returning NaN.
  6. Fix the bug in cartLogic.ts, recompile, and verify the total is now calculating correctly.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.