TypeScript, being the superset of JavaScript, makes it very convenient to write applications that have support for things like data types and generics to mention a few. However in order to be able to execute TypeScript code we need to transpile it to JavaScript. Having this JavaScript code also means that, when looking at our application code in the browser, we won't be able to see the TypeScript source code.
There are of course ways that we can do to overcome this and in this article we are going to be discussing how to debug TypeScript in web browsers by using source maps.
Source maps are special files that get created explicitly for JavaScript or CSS files. The idea is simple - imagine a bunch of JavaScript files or even SASS generated CSS files that get minified and concatinated in one single file. There's no way that we can debug using these files in the browser.
Having a source map will allow us to map our minified (or otherwise modified files) to their sources and be able to view the source in the browser.
On top of being able to see the original source we can also add breakpoints easily and further debug our application.
Now, in order to generate a source map, we'll be using the tsc
transpiler with the --sourceMaps true
option. Let's take a look at a very simple example and write some TypeScript code first:
interface IWarrior {
name: string;
health: number;
fight: Function;
}
let myWarrior: IWarrior = {
name: 'John the Nomad',
health: 100,
fight: function () {
return `"${this.name}" attack!`;
},
};
console.log(myWarrior.fight());
Now let's go ahead and transpile our code by executing tsc --sourceMaps true
.
The result is going to be a JavaScript file with the following line appended at the end:
//# sourceMappingURL=app.js.map
And we also have a map file generated with the following content:
{
"version": 3,
"file": "app.js",
"sourceRoot": "",
"sources": ["app.ts"],
"names": [],
"mappings": "AAMA,IAAI,SAAS,GAAa;IACxB,IAAI,EAAE,gBAAgB;IACtB,MAAM,EAAE,GAAG;IACX,KAAK,EAAE;QACL,MAAM,CAAC,OAAI,IAAI,CAAC,IAAI,eAAW,CAAC;IAClC,CAAC;CACF,CAAC;AAEF,OAAO,CAAC,GAAG,CACT,SAAS,CAAC,KAAK,EAAE,CAClB,CAAC"
}
The source map is really just a JSON document that has a few properties:
So we have the generated filename, the source and the mapping between the two that uses Base 64 VLQ (Variable-Length Quality) encoding. This encoding stores letters against numbers: for example 0 - A
, 1 - C
so on and so forth. (There are some online Base64 VLQ (de)coders available)
We can use a source map visualization tool to actually explore how the mapping works. This tool is really great at showing us how the original source (app.ts) maps to the generated file (app.js) pretty much term by term.
Now that we have a source map available we can open the application in a browser and see that under the 'Sources' tab (for Chrome) or 'Debug' (Firefox/Safari) the original .ts
file also appears:
Notice how we can also add breakpoints and see the values of the variables during runtime.