To make class fields or methods accessible only to the class and to the subclasses, we have to use the keyword protected
before writing the class field and methods in TypeScript.
TL;DR
// a simple class
class Person {
name: string;
protected age: number; // <- this is a protected field
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
// 👇🏽 this is a protected method
protected sayGreeting() {
console.log(`Hi, ${this.name}`);
}
}
// another class that extends the `Person` class
class Admin extends Person {
department: string;
constructor(name: string, age: number, department: string) {
super(name, age);
this.department = department;
}
// get the fields from the
// `Person` and `Admin` class
// and log those values to the console
showDetails() {
console.log({
name: this.name,
age: this.age,
department: this.department,
});
}
}
// create an instance of the `Admin` class
const john = new Admin("John Doe", 23, "Technical");
// try to access the protected field `age` and
// `sayGreeting` method of the `Person` class
// Error ❌. Property 'age' is protected and only
// accessible within class 'Person' and its subclasses.
console.log(john.age);
// Error ❌. Property 'sayGreeting' is protected and only
// accessible within class 'Person' and its subclasses.
john.sayGreeting();
For example, let's say we have a class called Person
with 2 fields called name
and age
, a constructor
, and a method called sayGreeting
like this,
// a simple class
class Person {
name: string;
age: number;
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
sayGreeting() {
console.log(`Hi, ${this.name}`);
}
}
Currently, all the fields
and methods
are public
by default and can be accessed from an instance of the class.
Now let's make the age
field and the sayGreeting
method only accessible to the Person
class and any subclasses from it. To do that we need to use the protected
keyword before the age
field and the sayGreeting
method like this,
// a simple class
class Person {
name: string;
protected age: number; // <- this is a protected field
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
// 👇🏽 this is a protected method
protected sayGreeting() {
console.log(`Hi, ${this.name}`);
}
}
After making the field and method protected, to test it out let's make a new class called Admin
that extends the Person
class.
To know more about extending classes see the blog on How to inherit properties and methods using class in JavaScript. This is written in the context of JavaScript ES6 class but the concept is the same in TypeScript.
Let's make the Admin
class that extends the Person
class and add a method called showDetails
like this,
// a simple class
class Person {
name: string;
protected age: number; // <- this is a protected field
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
// 👇🏽 this is a protected method
protected sayGreeting() {
console.log(`Hi, ${this.name}`);
}
}
// another class that extends the `Person` class
class Admin extends Person {
department: string;
constructor(name: string, age: number, department: string) {
super(name, age);
this.department = department;
}
showDetails() {
// cool code here
}
}
Now let's access all the fields from the Person
class, that is the name
and age
field as well as the field from the Admin
class and log the contents to the console like this,
// a simple class
class Person {
name: string;
protected age: number; // <- this is a protected field
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
// 👇🏽 this is a protected method
protected sayGreeting() {
console.log(`Hi, ${this.name}`);
}
}
// another class that extends the `Person` class
class Admin extends Person {
department: string;
constructor(name: string, age: number, department: string) {
super(name, age);
this.department = department;
}
// get the fields from the
// `Person` and `Admin` class
// and log those values to the console
showDetails() {
console.log({
name: this.name,
age: this.age,
department: this.department,
});
}
}
As you can see that we have accessed the age
field of the Person
class in the showDetails
method of the Admin
class. This is because the age
field is protected
and is available to the subclasses of the Person
class.
Now let's create an instance of the Admin
class and try to access the protected age
field and sayGreeting
method of the Person
class like this,
// a simple class
class Person {
name: string;
protected age: number; // <- this is a protected field
constructor(name: string, age: number) {
this.name = name;
this.age = age;
}
// 👇🏽 this is a protected method
protected sayGreeting() {
console.log(`Hi, ${this.name}`);
}
}
// another class that extends the `Person` class
class Admin extends Person {
department: string;
constructor(name: string, age: number, department: string) {
super(name, age);
this.department = department;
}
// get the fields from the
// `Person` and `Admin` class
// and log those values to the console
showDetails() {
console.log({
name: this.name,
age: this.age,
department: this.department,
});
}
}
// create an instance of the `Admin` class
const john = new Admin("John Doe", 23, "Technical");
// try to access the protected field `age` and
// `sayGreeting` method of the `Person` class
// Error ❌. Property 'age' is protected and only
// accessible within class 'Person' and its subclasses.
console.log(john.age);
// Error ❌. Property 'sayGreeting' is protected and only
// accessible within class 'Person' and its subclasses.
john.sayGreeting();
As you can see that both the access to the protected properties resulted in an error saying that it can be accessed only inside the class or any subclasses of it.
We have successfully made the class field and method only accessible to the class and the subclasses. Yay 🥳!
See the above code live in codesandbox.
That's all 😃!