Sunday, November 4, 2018

TypeScript - Compiler Behavior

Let us take a step back and understand how the compiler works. Let us consider the following example:

let myCity:string = "Hyderabad";
let cityElevation: number = 505;

we save this file as city-App.ts

Let us compile this file using tsc. On compilation we will have city-App.js file in the same folder.
$ ls -l city-App.*
-rw-r--r-- 1 ubuntu ubuntu 51 Nov  4 17:19 city-App.js
-rw-rw-r-- 1 ubuntu ubuntu 65 Nov  4 17:16 city-App.ts
$
Let us check the content of the javascript file: city-App.js

var myCity = "Hyderabad";
var cityElevation = 505;

Now let us modify the content of the TypeScript file to modify the myCity variable and assign it a number.

let myCity:string = "Hyderabad";
let cityElevation: number = 505;
myCity = 505;

On compilation, we have received the following error:
$ tsc city-App.ts
city-App.ts:3:1 - error TS2322: Type '505' is not assignable to type 'string'.

3 myCity = 505;
  ~~~~~~

$
Now, let us observe the corrsponding JavaScript file: city-App.js

We observe that it has compiled to:
var myCity = "Hyderabad";
var cityElevation = 505;
myCity = 505;


Now, this is surprising. If the compilation has thrown an error, then why did it modify the JavaScript file to include the change? This is because, TypeScript thinks, maybe there are some dependent files which may need this code. Hence, it will include the modification in the JavaScript file.

But, it is not a TypeScript friendly code.

Now, before we fix the above problem, let us look at our current version of tsconfig.json file:

{
"compilerOptions": {
/* Basic Options */
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"noImplicitAny":false,
"sourceMap":false
},
"exclude":[
"node_modules"
]
}

In this file, we configure the behaviour of our TypeScript compiler. This file gets created when we executed the following command at the command prompt:

$ tsc --init

Basic options are:

"exclude":[
"node_modules"
]

This excludes the node_modules folder during compilation step.

"module": "commonjs",

This tells the TypeScript compiler to resolve the compiled code to the commonjs format.

"target": "es5",
This mentions the target of JavaScript version to which we want to compile. This is es5 as - es5 is used in all the modern web browsers.

"strict": true,


Now, to fix the problem of JavaScript file getting modifed - let us add the following line of code in our tsconfig.json:

"noEmitOnError": true

By default, this value is false. Now, that we are setting this to true. On encountering error during compilation, TypeScript compiler should not create a new JavaScript file.

Let us check the modified tsconfig.json:

{
"compilerOptions": {
/* Basic Options */
"target": "es5",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"noImplicitAny":false,
"sourceMap":false,
"noEmitOnError": true
},
"exclude":[
"node_modules"
]
}


Now, if we compile our incorrect TypeScript file.

$ tsc
city-App.ts:3:1 - error TS2322: Type '505' is not assignable to type 'string'.

3 myCity = 505;
  ~~~~~~

$ ls -l city-App.*
-rw-rw-r-- 1 ubuntu ubuntu 79 Nov  4 17:22 city-App.ts
$

We can see that no new JavaScript file was created. Please note, I have used the command tsc for compilation and not tsc followed by filename. If I would have used as follows:

$ tsc city-App.ts

Then a JavaScript file would have still been generated. This is because when we use tsc with file after it, the TypeScript compiler ignores using tsconfig.json.


Reference:




No comments:

Post a Comment