mihir hapaliya
mihir hapaliya

Reputation: 297

Why private variable in a class is treated as public in the transpiled code

I have added following class in typescript

class Person {
    private variable1;
    public varibele2;

    Person(){
        this.variable1 = 'abc';
        this.varibele2 = 'xyz'; 
    }

    public getVariable1(){
        return this.variable1;        
    }
}

So When I compile the code using tsc , it generates the following code

var Person =  (function () {
    function Person() {
    }
    Person.prototype.Person = function () {
        this.variable1 = 'abc';
        this.varibele2 = 'xyz';
    };
    Person.prototype.getVariable1 = function () {
        return this.variable1;
    };
    return Person;
}());

Since variable1 is private should not be accessible by the obj of that class(which is happening in typescript code).

Same behavior should be happened into transpiled es5 code(But not happening).

In above example's transpiled code I am creating object of the Person

var p = new Person();
console.log(p.variable1); // undefined 
p.variable1 = 'abc1';  // setting value to variable 1 
console.log(p.variable1); // 'abc1'
console.log(p.getVariable1()); // 'abc1'

In above code I should not be able to set or get the value of variable1.

var p = new Person();
console.log(p.getVariable1()); // 'undefined' 
p.variable1 = 'abc1';  // setting value to variable1 
console.log(p.getVariable1()); // 'abc1'

In above code , I am trying fetch the value using p.getVariable1() and I get undefined.Since value is already assigned in constructor of the class , it should be available through p.getVariable1()

var p = new Person();
console.log(p.variable2); // undefined
p.variable2 = 'xyz1'; // setting value
console.log(p.variable2);// 'xyz1'

In above code Variable2 should retrun 'xyz' but it's not. Once i assign value to it , it returns.

So Behavior of private and public variables are same in transpiled code and its very confusing. Its not returning the value which is assigned in constructor.

Upvotes: 4

Views: 2053

Answers (4)

Shrirang Edgaonkar
Shrirang Edgaonkar

Reputation: 41

if the transpiled code is not using closure to make it private it means I can flout the variables when using it as a javascript library because I will never know what is private what is not. So the answer is transpiling the way typescript does is incorrect and not in true spirit of usage of javascript.

Upvotes: 1

Romain Deneau
Romain Deneau

Reputation: 3061

First, to respond to your main question:

Why private variable in a class is treated as public in the transpiled code.

It's true that private properties, as well as readonly properties, are transpiled into plain properties hence "public". I think it's to simplify and boost transpilation TS→JS and to favor using TypeScript everywhere, where warnings or errors are emitted when performing invalid operations on these kind of properties: accessing a private property outside the class, reassigning a readonly property...

But you give examples with very strange behaviors. They are not due to TypeScript transpilation. I notice some issues with your class Person that have led to them:

  • In ES6 and TypeScript, the class constructor is defined using the keyword constructor, not the class name. It's even more confusing because the constructor is transpiled into a function constructor named like the class, here Person.
  • There's a typo with the second property: varibele2 instead of variable2. This is why console.log(p.variable2) can't print the expected value.

Fixing these issues, the code behaves more logically.

class Person {
    constructor(private _variable1 = 'abc', public variable2 = 'xyz') { }

    public get variable1() { return this._variable1; }
}

console.log(new Person()); // → Person { v1: [Getter], v2: "xyz", _v1: "abc", __proto__... }

The transpiled code is available through the TypeScript playground.

Note: I favor another syntax:

  • Properties are declared directly in the constructor: it's more compact, it enables type inference and we can specify other initial values.
  • Private variable are named _x to ease writing a getter get x() { return this._x; }. It's also a commonly used JavaScript convention to indicate that the variable is meant to be private, without a complex pattern to really have a private property.

Upvotes: 2

mihir hapaliya
mihir hapaliya

Reputation: 297

In following case as per my understanding, variable2 comes undefined because object p don't contain that variable.

In following code we are including variable using p.variable2 = 'xyz1' into object p. so in the third line we get the value of that variable.

var p = new Person();
console.log(p.variable2); // undefined
p.variable2 = 'xyz1'; // setting value
console.log(p.variable2);// 'xyz1'

Still the question is since typescript has declared the variable then why javascript(compiled code) object doesn't contain those variables?

Upvotes: 0

Nicholas Tower
Nicholas Tower

Reputation: 84982

To continue our discussion from the comments, here's the benefit that you get from using public vs private:

example of typescript errors

The IDE will tell you immediately that you're doing something you're not supposed to do. If you ignore these errors, the code will compile to javascript and run, but the point is that you don't ignore these errors. When you write bad code like this, typescript tells you there's a problem, and then you can fix the problem. If you have a build process, you can set it up so that these typescript errors will fail the build, thus forcing you to fix the problem before deploying.

Typescript is a tool to help you write better javascript code, by catching errors earlier and easier. It is not a tool to change the way javascript works. Typescript does not provide runtime type checking, and if that's what you're after, you won't find it. If you need closures to hide variables, then create a closure yourself.

Upvotes: 3

Related Questions