Why does TypeScript when compiled, convert "let" to " var " in variables?

If let variavel = "valor"; is also supported in JavaScript, because in TypeScript compilation, it transforms to var variavel = "valor"?

Take the test right here :

function foo(){
  var x = 1;
  let y = 3;
  if (true){
    var x = 2;
    let y = 4;
    console.log(x); //Irá resultar 2.
    console.log(y); //Irá resultar 4.
  }
  console.log(x); //Irá resultar 2 porque o escopo do 'var' abrangiu toda a função foo().
  console.log(y); //Irá resultar 3 porque o escopo do 'let' abrangiu apenas o bloco, diferente da atribuição na expressão if.
}
Author: Maniero, 2018-08-20

2 answers

This is because the --target (or just -t) by default will convert to ES3, very similar to ES5, but has many APIs that do not exist in it (although in this case it depends on the browser) and will not use string mode which is something from ES5, as it is said in the documentation:

Using ES3 as the default is probably to try to be as backward compatible as possible, of course this turn and a half can imply some unwanted effect.

If you believe that you will use typescript only in environments that will support ES6 + then just specify to convert to the desired one, remembering that let is not from ES5, so if you want to use exactly as it is just adjust in the compiler:

tsc script-ivan.ts -t ES6

Supported targets are:

  • "ES3" (default)
  • "ES5"
  • "ES6" or "ES2015"
  • "ES2016"
  • "ES2017"
  • "ES2018"
  • "ES2019"
  • "ES2020"
  • "ESNext "(these are all the latest features proposed in https://github.com/tc39/proposals , which of course there are no guarantees to run in all environments, since this is to "convert")

So that's the reason, the default for now is ES3, but you have full control of adjusting to what suits you.

Typescript also has many environments supported and each one works in a way, so I'll try to summarize, tsconfig.json is the configuration file in most projects that use TypeScript, so basically you can configure in it how you want the conversion to be, example including some libs and conversion to ES2019:

{
  "$schema": "https://json.schemastore.org/tsconfig",

  ...
 
  "compilerOptions": {
    "lib": ["es2019", "es2020.promise", "es2020.bigint", "es2020.string"],
    "module": "commonjs",
    "target": "es2019",

    ...
  }  
}

Https://www.typescriptlang.org/docs/handbook/tsconfig-json.html

 4
Author: Guilherme Nascimento, 2021-01-12 00:07:44

I can not answer authoritatively in particular, but from what I know of compilation and transpilation , it makes some sense because the extra control that let gives is the scope, which the TypeScript compiler has already guaranteed to be adequate, so there is no reason to send to the JS code something for it to check again. Once it knows it's in the right scope, when the JavaScript code is generated there's no more reason for the JS compiler to take care of it. It would be a work of redundant compilation. I imagine compiling var in JS is faster than compiling let.

The JS code generated by the TS doesn't need to be robust, it doesn't need to be readable, it's not for humans, it needs to be efficient and well done for everything to work properly, it's another level of abstraction.

In fact it can be observed that it protects the variable by changing its name where it has the let:

function foo() {
    var x = 1;
    var y = 3;
    if (true) {
        var x = 2;
        var y_1 = 4;
        console.log(x);
        console.log(y_1);
    }
    console.log(x);
    console.log(y);
}

See working and transpiled in TypeScript Playground. I also put on GitHub for future reference .

Also using var ensures that it runs on older browsers that do not have let.

 6
Author: Maniero, 2020-07-30 20:16:47