-2

I have this TS code:

export namespace Constants
{
    export var x = 0;        
}

If I compile it with 'tsc' I get this JS code:

"use strict";
exports.__esModule = true;
exports.Constants = void 0;

var Constants;
(function (Constants) {
    Constants.x = 0;
})(Constants = exports.Constants || (exports.Constants = {}));

My question is. Why 'tsc' compiles a namespace into an IIFE instead of a simple and much more readable object like this?

var Constants = {};
Constants.x = 0;

Is there any particular reason?

There are other questions similar to this. Except that they don't give any true answer. What makes this question different is that a namespace is meant to be only a simple container to segregate code, then it must be as simple and readable as possible and an IIFE isn't the best solution to do that.

Alter Ego
  • 13
  • 1
  • 4
  • 1
    @MarioSantini The generated ES5 code given in this question is perfect. There isn't one character to change. Obviously, the TypeScript team cares about the generated code. – Paleo Apr 21 '21 at 08:56
  • @Paleo I deleted my comment and made an answer as was too long. I hope it make more sense. – Mario Santini Apr 21 '21 at 09:05

2 Answers2

1

A namespace is a scope. And the classic way to provide a scope in JavaScript is to put the code in a function.

In particular, the IIFE is a way to encapsulate local variables:

export namespace Constants
{
  const val = 2
  export const x = val * 2;
}

// Here, 'val' must be inaccessible.
// And we can create another 'val' variable:

const val = 3; // OK

With the "simple object" implementation, the code upstairs would be compiled to:

const Constants = {};
const val = 2
Constants.x = val * 2;

// With this implementation, 'val' could be accessed outside the namespace at runtime.
// And we couldn't create another 'val' variable:

const val = 3; // Error: already defined.
Paleo
  • 21,831
  • 4
  • 65
  • 76
  • I Apologize but I think you don't get the point. I agree with you, «it is a way to encapsulate local variables.» The point is: why an IIFE and not a simple object? – Alter Ego Apr 21 '21 at 08:23
  • Sorry Paleo, read carefully the question before reply. Obviously, you are right «Without an IIFE...'val' would be accessible outside the namespace at runtime». But in this case, your implementation is out of the current contest. – Alter Ego Apr 21 '21 at 08:40
  • @AlterEgo You need to clarify what is the "current contest". – Paleo Apr 21 '21 at 10:46
  • @AlterEgo - care to read [the spec](https://github.com/microsoft/TypeScript/blob/master/doc/TypeScript%20Language%20Specification%20-%20ARCHIVED.pdf) before replying? Page 14, 1.10 Namespaces – Oleg Valter is with Ukraine May 29 '21 at 20:28
0

I wrote a comment, but maybe an answer is the proper way to express better my point here.

I don't think it is possible to answer your question, as it is a matter of choice made by the TypeScript team.

Anyway I will write my thoughts about this topic here.

I don't think they care too much about the readability of the generated JavaScript code.

Rather they just care that it works as expected, and the fact that your simple example is not optimized, I guess is just the fact that they didn't think it should be optimized.

A namespace is exactly like a module, and can contain code, functions, classes. It can be big and complex.

And even in the simple cases like the one you showed a plain object would act in the same way as a function, in JavaScript es5 is not the same semantically.

If you use a plain object in TypeScript it would be, but a namespace is a module, and the only equivalence on JavaScrip es5 is a function.

I think it can change if you target a different version of JavaScript, for example one that have modules.

Mario Santini
  • 2,905
  • 2
  • 20
  • 27