Why can I access TypeScript private members when I shouldn't be able to?

Just as with the type checking, the privacy of members are only enforced within the compiler.

A private property is implemented as a regular property, and code outside the class is not allowed to access it.

To make something truly private inside the class, it can't be a member of the class, it would be a local variable created inside a function scope inside the code that creates the object. That would mean that you can't access it like a member of the class, i.e. using the this keyword.


JavaScript does support private variables.

function MyClass() {
    var myPrivateVar = 3;

    this.doSomething = function() {
        return myPrivateVar++;        
    }
}

In TypeScript this would be expressed like so:

class MyClass {

    doSomething: () => number;

    constructor() {
        var myPrivateVar = 3;

        this.doSomething = function () {
            return myPrivateVar++;
        }
    }
}

EDIT

This approach should only be used SPARINGLY where it is absolutely needed. For example if you need to cache a password temporarily.

There are performance costs to using this pattern (irrelevant of Javascript or Typescript) and should only be used where absolutely necessary.


Since TypeScript 3.8 will be released you will be able to declare private field which can’t be accessed or even detected outside of the containing class.

class Person {
    #name: string

    constructor(name: string) {
        this.#name = name;
    }

    greet() {
        console.log(`Hello, my name is ${this.#name}!`);
    }
}

let jeremy = new Person("Jeremy Bearimy");

jeremy.#name
//     ~~~~~
// Property '#name' is not accessible outside class 'Person'
// because it has a private identifier.

Private fields starts with # character

Please note that these private fields will be something different than fields marked with private keyword

Ref. https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/