As a frontend developer, one of the things you should know is how TypeScript compiler works. Sooner or later you will work with this language (which I sincerely wish you!), so it’s good to know your stuff 😉
In this article, I will explain TypeScript compiler to you in simple terms. We will avoid complex stuff – only what you need for your everyday frontend developer’s work. We will not explore the inner workings of the TypeScript compiler Instead, we’ll see some practical implications of its workings for TypeScript developer. Let’s dive in 🙂
Few basic facts about TypeScript
For starters, let’s establish some quick facts about TypeScript as a language.
Browser doesn’t understand TypeScript
The answer is that TypeScript cannot be run directly by a web browser (or NodeJS).
Let’s take this trivial TypeScript code:
and try to paste it into Google Chrome’s console in order to execute it:
As you can see, it fails. The
TypeScript is for developers
As we have just discovered, types must be removed by the TypeScript compiler before the code can be executed by the browser. In fact, this line of TypeScript:
This is effectively the same code we wrote in TypeScript, but without type annotations.
Wrong data types assignments will only be detected at compile time:
but as soon as it’s compiled, this protection is not there anymore 🤷♂️
This discovery means that TypeScript is for developers. Its job is to make our lives easier. Of course, in the end it also improves the end users’ experience, because programming in TypeScript is much better than using pure JS. But you can already see that TypeScript it not present at runtime at all. It only protects us until the compilation step by static types checking.
The philosophy is more or less as follows 😀:
TypeScript compiler in practice
TypeScript compiler is actually a CLI tool called
tsc. It can be installed globally on your machine and used directly or built into your IDE. Refer to official documentation for installation details.
The compiler can also be installed locally in your project. It can then be set up as part of the build pipeline, which is supported by many bundlers. That’s why, when working on a TypeScript project, you may never encounter any direct usages of the
In order to make working with TypeScript compiler easier, you should use a
tsconfig.json file. It’s a JSON file containing all compilation settings. This is quite important, because, in opposite to C# or Java compilers, the TypeScript’s one allows for quite extensive (and flexible) configuration.
When you use the
tsc command, it looks for
tsconfig.json file in the current directory or any of the parent directories until it finds one. You can also provide a custom
tsconfig.json location via
tsconfig.json file you get after initializing a new TypeScript project with
tsc --init looks as follows:
We will not explore all the individual settings in this article. The official documentation does a great job.
TypeScript compiler – example
Let’s now see how it works.
Having a bit more complex TypeScript file as an example:
.ts extension. This tells the compiler that this file contains TypeScript code.
tsc installed globally, we can compile it by executing the following command:
Few things to note:
- there is no information about types in the
- notice there is no
- comments are left untouched
This explains how the TypeScript compiler works. It also confirms what we stated before, that TypeScript is for programmers. As soon as your code is deployed to production, the types you added in
.ts files are absent. The way this process is built gives a lot of advantages, but it may also be a source of confusion – let’s see how exactly.
TypeScript compilation flaws
Finally, knowing how TS -> JS compilation works, let’s quickly explore some of its common flaws.
No runtime protection
As you now know, TypeScript stripes out the types during compilation. It means that the information about types is not present at runtime (when our code executes). Because of that, we are not protected by TypeScript at runtime. Consequently, if an input comes from a user and the inputs themselves are not well validated, we may still get runtime type errors. Imagine that your code expects a
number, but the user enters a
string because of lack of proper input validation. TypeScript will not protect you here.
The same applies to validating API responses. Most data from HTTP APIs comes in a form of JSON. In TypeScript, we can represent such data as
interface. Based on those expected shapes of data, we use objects of a given type and assume that given properties are present on them or not. However, APIs may change, and TypeScript will again not protect us at runtime. We still need to resort to alternative solutions for runtime types validation.
To be completely clear – I don’t think that no runtime protection is something TypeScript lacks. On the contrary – I love the flexibility of TypeScript which this approach gives. It’s just how the language has been designed, and we should be aware of that 🙂
When working on a TypeScript project, the code you see on production is different from the one in your IDE. Sometimes not only types are stripped out by TypeScript compiler, but as you saw earlier it may also convert some constructs to the other (like changing a
class to a
function). It makes debugging, especially directly on production, more complex.
In order to place breakpoints and actually have them hit in your TypeScript code, you need source maps. It does the job in most cases, but adds to the complexity at the same time, not always working seamlessly.
TypeScript is sometimes too strict
There are countless memes about that, but here is the one I like:
Joking apart, most things TypeScript complaints about can be configured/turned off in
I hope that now you feel more comfortable working with TypeScript compiler 🙂
If you’re a .NET developer, and you enjoyed this article, I think you may also find my free guide useful: