Types vanish at compile time
At customs, declarations are needed only at the border. Once the parcels are checked, the papers are thrown away, and inside the country nobody reads them again. tsc does the same: it first checks the types, then writes JavaScript that has none of them. This is called type erasure.
Let's see what tsc leaves of a file hello.ts with annotations. Press "Next step" and watch what each highlighted TypeScript line turns into.
The parameter and the result had : string annotations; the JavaScript has none, and the function stays.
What is left in hello.js
After compilation, in hello.js:
- all the annotations are gone:
: stringon the parameter and the result,: stringand: numberon the variables; - everything that runs is still there: the function, the template literal, the values
"Anna"and3, theconsole.logcall; - a line
"use strict";appeared at the top:tscadded it. That is JavaScript's own strict mode, nottsc's, and it has nothing to do with types.
The result is plain JavaScript without a word about types. The command node hello.js runs it like any other .js file.
Why erase the types
Why not keep the annotations in the JavaScript? Because they are not JavaScript. When a browser or Node.js meets : string in a .js file, it stops with a syntax error before the first line runs. That is why tsc cuts the types out: without them the file makes sense to both the browser and Node.js.
No types at run time
Since hello.js has no types, nobody checks them while the program runs. There was one check, before the run, from the program's text. That is why types do not protect you from data that appears only while the program runs:
- text a user typed into a form;
- a server's response;
- the contents of a file.
In the customs picture such data enters the country around the border, with no declaration: tsc has never seen it. If a value needs checking, the program does it itself with JavaScript, for example with typeof.
Interviewers often ask whether TypeScript types exist at run time. They do not: tsc erases them at compile time, and the running program is JavaScript alone.
An error does not stop the file
Here the customs picture stops working. A real inspector holds back a parcel with a wrong declaration, while tsc reports the error and writes the .js anyway. Checking types and writing JavaScript are two separate jobs, and the second does not wait for the first to succeed.
To keep tsc from writing the file while the code has errors, you need the --noEmitOnError flag:
$ tsc --noEmitOnError hello.tsWith it, no new hello.js appears when there is an error. An old one, if it is left from an earlier compilation, stays as it was.
Common mistake
Seeing a tsc message and running hello.js anyway. Let's go back to the function from the first lesson of this theme:
function formatPrice(price: number): string {
return price.toFixed(2);
}
console.log(formatPrice(100));
console.log(formatPrice("100")); // ✗error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.tsc hello.ts reports this error but writes hello.js all the same. The command node hello.js prints 100.00, and on the second call the program stops:
TypeError: price.toFixed is not a functionThe types are erased, and the string "100" reached toFixed as in JavaScript without any TypeScript. The fix is to clear the errors tsc reported first, and only then run the program.
Key points
tscfirst checks the types, then writes JavaScript without them: this is type erasure.hello.jshas no annotations, so at run time types check nothing.tscnever saw data that arrives while the program runs: it is checked with JavaScript, for exampletypeof.tscwrites the.jseven when there are errors, and the--noEmitOnErrorflag forbids that.