Public and private accessors
A further object-oriented principle that is used in encapsulation is the concept of data hiding—that is, the ability to have public and private variables. Private variables are meant to be hidden to the user of a particular class—as these variables should only be used by the class itself. Inadvertently exposing these variables can easily cause runtime errors.
Unfortunately, JavaScript does not have a native way of declaring variables private. While this functionality can be emulated using closures, a lot of JavaScript programmers simply use the underscore character (_) to denote a private variable. At runtime though, if you know the name of a private variable, you can easily assign a value to it. Consider the following JavaScript code:
var MyClass = (function() { function MyClass() { this._count = 0; } MyClass.prototype.countUp = function() { this._count ++; } MyClass.prototype.getCountUp = function() { return this._count; } return MyClass; }()); var test = new MyClass(); test._count = 17; console.log("countUp : " + test.getCountUp());
The MyClass variable is actually a closure, with a constructor function, a countUp function, and a getCountUp function. The _count variable is supposed to be a private member variable that is used only within the scope of the closure. Using the underscore naming convention gives the user of this class some indication that the variable is private, but JavaScript will still allow you to manipulate the _count variable. Take a look at the second last line of the code snippet. We are explicitly setting the value of _count to 17, which is allowed by JavaScript, but not desired by the original creator of the class. The output of this code would be countUp : 17.
TypeScript, however, introduces the public and private keywords that can be used on class member variables. Trying to access a class member variable that has been marked as private will generate a compile time error. As an example of this, the previous JavaScript code can be written in TypeScript as follows:
class CountClass { private _count: number; constructor() { this._count = 0; } countUp() { this._count ++; } getCount() { return this._count; } } var countInstance = new CountClass() ; countInstance._count = 17;
Here, on the second line of our code snippet, we have declared a private member variable named _count. Again, we have a constructor, a countUp function, and a getCount function. If we compile this file, the compiler will generate an error:
hello.ts(39,15): error TS2341: Property '_count' is private and only accessible within class 'CountClass'.
This error is generated because we are trying to access the private variable, _count, in the last line of the code.
The TypeScript compiler is therefore helping us to adhere to public and private accessors by generating a compile error when we inadvertently break this rule.