Create Truly Private Class Fields Using the #fieldName Syntax

Marius Schulz
InstructorMarius Schulz

Share this video with your friends

Send Tweet
Published a year ago
Updated a year ago

This lesson introduces private class fields which (unlike regular class fields) cannot be examined or modified outside of the class they're defined in. We're going to contrast private class fields with TypeScript's private modifier and public class fields.

We're also going to take a look at the JavaScript code that the TypeScript compiler emits when downlevel-compiling private class fields. Note that this code requires that the JavaScript runtime implement the WeakMap data structure (introduced as part of ES2015). Finally, we're going to learn how we can use closures to get true privacy guarantees in older runtime environments that do not implement WeakMap.

Additional Reading

Instructor: [0:00] Now that we've seen TypeScript's private modifier, let's go ahead and let's refactor this class to use truly private class fields. All I need to do is rename the value field. I'm going to make sure the name begins with a # sign. This turns the value field into a truly private class field. Now, the value field can no longer be accessed in any way from outside of the counter class.

[0:25] Note that unlike the private modifier we've seen before, private class fields are not TypeScript-specific syntax. In fact, I can pull up the terminal, and I can run the index.ts file in Node directly because we're not using any TypeScript-specific syntax.

[0:42] Let's see what happens when we try to use the value field outside of the counter class. If I try to modify the value field by saying counter.value = -100, TypeScript now gives us an error. It's telling us that the property value is not accessible outside of the class counter because it has a private identifier. Its name begins with a # sign, so this makes it a truly private class field.

[1:10] If we now run the code again, we're finally getting an error at runtime. It's saying that the private field value must be declared in an enclosing class. Notice that this is considered a syntax error. Writing counter.value outside of the defining class is not even considered valid syntax.

[1:31] The great thing about private class fields is that they're truly private. Outside of the class, not only can we not access the value of these fields, we do not even know about their existence. This gives us the freedom to rename and refactor our private class fields as much as we want without having to worry that consumers of our class are depending on its internals, intentionally or unintentionally.

[1:55] For example, we might decide to rename the field to something like count. We can safely make that refactoring without having to worry about breaking a consumer of our class. There is one caveat when you're using private class fields in TypeScript, and that is that the language level you're targeting needs to be ES2015 or higher.

[2:16] In your TSConfig file, you want to make sure that the target property is set to at least ES2015. This is a requirement because the TypeScript compiler is emitting a WeakMap into the generated JavaScript to implement that notion of true privacy, and WeakMaps have only been supported as of ES2015.