JavaScript private class fields and the TypeScript private modifier
Tags: javascript, typescript, webdev
Published: 2020-01-14 09:26:15

---
title: "JavaScript private class fields and the TypeScript private modifier"
published: true
description: "In this post we'll shed light on ECMAScript private fields and see how they compare to the TypeScript private modifier."
tags: javascript, typescript, webdev
canonical_url: https://www.valentinog.com/blog/private/
---

_In this post we'll shed some light on JavaScript private class fields and see how they compare to the TypeScript private modifier._

## JavaScript private class fields and the need for privacy

Historically **JavaScript had no native mechanism for protecting variables from access**, unless of course, **the quintessential closure**.

Closures are the foundation for a lot of private-like patterns in JavaScript like the popular module pattern. But after ECMAScript 2015 classes took over in recent years, developers felt **the need for more control over classes member privacy**.

The **class field proposal** (at the time of writing in stage 3) tries to solve the problem with the introduction of **private class fields**. 

Let's see how they look.

## JavaScript private class fields, an example

Here's a JavaScript class with private fields, note that unlike "public" members every **private field must be declared before access**:

```javascript
class Person {
  #age;
  #name;
  #surname;

  constructor(name, surname, age) {
    this.#name = name;
    this.#surname = surname;
    this.#age = age;
  }

  getFullName() {
    return `${this.#name} + ${this.#surname}`;
  }
}
```

**Private class fields are not accessible from outside the class**:

```javascript
class Person {
  #age;
  #name;
  #surname;

  constructor(name, surname, age) {
    this.#name = name;
    this.#surname = surname;
    this.#age = age;
  }

  getFullName() {
    return `${this.#name} + ${this.#surname}`;
  }
}

const marta = new Person("Marta", "Cantrell", 33);
console.log(marta.#age); // SyntaxError
```

This is true "privacy". At this point if you now a bit of TypeScript you might ask what "native" private fields have in common with the **private modifier in TypeScript**.

Well, the answer is: **nothing**. But why?

## The private modifier in TypeScript

The **private modifier in TypeScript** should be familiar to developers coming from more traditional backgrounds. In brief, the keyword is meant to deny class members access from outside the class.

But let's not forget, **TypeScript is a layer on top of JavaScript** and the TypeScript compiler is supposed to strip away any fancy TypeScript annotation, including **private**. 

That means the following class doesn't do what you think it does:


```typescript
class Person {
  private age: number;
  private name: string;
  private surname: string;

  constructor(name: string, surname: string, age: number) {
    this.name = name;
    this.surname = surname;
    this.age = age;
  }

  getFullName() {
    return `${this.name} + ${this.surname}`;
  }
}

const liz = new Person("Liz", "Cantrill", 31);
// @ts-ignore
console.log(liz.age);
```
    
Without **// @ts-ignore**, accessing liz.age **throws an error only in TypeScript**, yet after the compilation you end up with the following JavaScript code:

```javascript
"use strict";
var Person = /** @class */ (function () {
    function Person(name, surname, age) {
        this.name = name;
        this.surname = surname;
        this.age = age;
    }
    Person.prototype.getFullName = function () {
        return this.name + " + " + this.surname;
    };
    return Person;
}());

var liz = new Person("Liz", "Cantrill", 31);
console.log(liz.age); // 31
```

As expected we're free to print liz.age. **The main take here is that private in TypeScript is not so private**, and it feels convenient only at the TypeScript level, not for "real privacy".

And now let's get to the point: **"native" private class fields in TypeScript**.

## Private class fields in TypeScript

**TypeScript 3.8 will support ECMAScript private fields**, not to be confused with the **TypeScript private modifier**.

Here's a class with private class fields in TypeScript:

```typescript
class Person {
    #age: number;
    #name: string;
    #surname: string;

    constructor(name:string, surname:string, age:number) {
        this.#name = name;
        this.#surname = surname;
        this.#age = age;
    }

    getFullName() {
        return `${this.#name} + ${this.#surname}`;
    }
}
```

Not so different from vanilla JavaScript, besides type annotations. Members cannot be accessed from the outside. But the **real problem with private fields in TypeScript is that they use WeakMap** under the hood. 

To compile this code we need to adjust the target compilation version in tsconfig.json, which must be at least **ECMAScript 2015**:

```json
{
  "compilerOptions": {
    "target": "es2015",
    "strict": true,
    "lib": ["dom","es2015"]
  }
}
```

This could be a problem depending on the target browser, unless you intend to ship a **polyfill for WeakMap, which at that point becomes too much work if it's just for the sake of writing fancy new syntax**.

There is always this tension in JavaScript, where you really want to use the new syntax, but on the other hand you don't want to let the UX down with a gazillion polyfills.

On the flip side I don't think you should worry too much about private class fields, even if you want to ship to newer browsers. At least for now. The **[support for private fields is almost non-existent](https://caniuse.com/#search=private%20class)**. Not even Firefox has implemented the proposal.

Let's see what the future holds.

## Conclusions

Still a proposal at the time of writing, [JavaScript class fields](https://github.com/tc39/proposal-class-fields) are interesting, but the support among browser vendors is poor. **What's your take on this feature**?

Here's mine:

- I like ES private class fields (though I dislike the #)
- I **never relied to much on private in TypeScript**, useful only at the TS level
- I'll wait until private class fields land in browsers
- I wouldn't use private class fields in TS today

To learn more about [TypeScript classes check this out](https://www.typescriptlang.org/docs/handbook/classes.html). 

The [official announcement for TypeScript 3.8 private fields](https://devblogs.microsoft.com/typescript/announcing-typescript-3-8-beta/#ecmascript-private-fields).