In this post you’ll learn how to create both public and private members in TypeScript classes, which we can use for both properties and methods.
JavaScript itself has no strict “private” capability, as per the design of the language, but with the addition of TypeScript in our workflow we get compile-time safety to stop private methods from being accessed.
What’s important to realize before we explore is even though properties and methods can be marked as public
and private
in TypeScript, they actually have no effect on the compiled output of our code.
By default all properties and methods, known as members, are public
. Some developers enjoy using the public
keyword alongside members but I feel like it’s not necessary due to TypeScript implicitly setting all members as public.
Let’s look at a basic class example:
class Product {
name: string;
price: number;
constructor(name: string, price: number) {
this.name = name;
this.price = price;
}
}
Based on what I’ve written above, we know that name
and price
are both public
by default. Meaning, the above code is the same as below:
class Product {
public name: string;
public price: number;
constructor(name: string, price: number) {
this.name = name;
this.price = price;
}
}
If you want to use the public
keyword, then feel free, but again I feel it’s not entirely necessary and creates more reading. We know things are public
by default.
Now here’s where things get interesting, and before we look at private
members let’s investigate the compiled TypeScript-to-JavaScript source code:
var Product = /** @class */ (function () {
function Product(name, price) {
this.name = name;
this.price = price;
}
Product.prototype.getName = function () {
return this.name;
};
return Product;
}());
Interesting! On the top level we have var Product
which encapsulates a Product
constructor function and is extended via the prototype
with a getName
function. This is done automatically for us to create private scope for our code.
But it’s not private, JavaScript has no private scope.
So what about the private
keyword in TypeScript, maybe that helps us? Not quite, so don’t get carried away.
A property or method marked as private
will simply throw an error if you try and access it from outside its scope boundary, for example a class.
class Product {
private name: string;
price: number;
constructor(name: string, price: number) {
this.name = name;
this.price = price;
}
}
const espresso = new Product('Espresso', 399);
// ❌ 'name' is private and only accessible within class 'Product'
console.log(espresso.name);
Similarly, if you mark a method as private
it can only be used inside the class
that defines it:
class Product {
private name: string;
price: number;
constructor(name: string, price: number) {
this.name = name;
this.price = price;
}
private getName() {
return this.name; // ✅ access allowed
}
}
const espresso = new Product('Espresso', 399);
// ❌ 'getName' is private and only accessible within class 'Product'
espresso.getName();
All public
properties are fully accessible outside of the class
they’re created from, whereas all private
properties and methods are not.
But… There is one thing you need to realize (and I’ve said it up top) - there is no private scope in JavaScript (yet…)!
So do not rely on the private
keyword to solve your problems here. Want to see the output code from the above example using private
?
Here:
var Product = /** @class */ (function () {
function Product(name, price) {
this.name = name;
this.price = price;
}
Product.prototype.getName = function () {
return this.name;
};
return Product;
}());
Yep, it’s exactly the same output whether or not you use public
or private
. TypeScript does not change JavaScript’s behavior when the code is compiled, and on the subject of private scope there is no silver bullet. The most we can do is encapsulate out logic within function scope and only expose methods we want to.
🏆 Check out my series of TypeScript Courses where you’ll learn TypeScript in-depth with real-world scenarios and examples to supercharge your JavaScript development.
That said, TypeScript takes care of some of the functionality for us, but when a class
is compiled with private
members, they will not be private. It is simply to stop you, and other developers, from accessing and using them in development.
Maybe one day we will see true “private” scope in JavaScript, until then be careful with whatever critical information you expose client-side, as if the code exists in the browser - it can be accessed and played with.