Debugging TypeScript in the browser
Older Article
This article was published 9 years ago. Some information may be outdated or no longer applicable.
TypeScript, being a superset of JavaScript, makes it convenient to write applications with support for data types, generics and more. But to actually run TypeScript, we need to transpile it to JavaScript. And once we’ve got that JavaScript, we can’t see the original TypeScript source code in the browser.
There are ways around this. Here we’ll look at how to debug TypeScript in web browsers using source maps.
Source maps
Source maps are special files created for JavaScript or CSS files. The idea is simple. Imagine a bunch of JavaScript files (or SASS-generated CSS files) that get minified and concatenated into a single file. There’s no way to debug using those files in the browser.
A source map lets us map our minified (or otherwise modified) files back to their sources, so we can view the original code in the browser.
On top of seeing the original source, we can also set breakpoints and step through our application.
Generate source maps
To generate a source map, we’ll use the tsc transpiler with the --sourceMaps true option. Let’s write some TypeScript 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 transpile with tsc --sourceMaps true.
The result is a JavaScript file with this line appended at the end:
//# sourceMappingURL=app.js.map
We also get a map file 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"
}
Understanding the source map
The source map is a JSON document with a few properties:
- version - the source map standard’s version
- file - the transpiled filename
- sourceRoot - an optional source root, useful for relocating source files on a server or removing repeated values in the “sources” entry
- sources - the original TypeScript source file
- names - a list of symbol names used by the mappings entry
- mappings - encoded mapping data
So we’ve got the generated filename, the source, and the mapping between the two using Base 64 VLQ (Variable-Length Quantity) encoding. This encoding stores letters against numbers: for example 0 - A, 1 - C and so on. (There are some online Base64 VLQ (de)coders available.)
Interpret Base 64 VLQ
We can use a source map visualisation tool to explore how the mapping works. It’s excellent at showing how the original source (app.ts) maps to the generated file (app.js) term by term.
Use the maps for debugging
With a source map in place, we can open the application in a browser. Under the “Sources” tab (Chrome) or “Debug” tab (Firefox/Safari), the original .ts file appears:
We can set breakpoints and inspect variable values during runtime.