How to make class fields or methods accessible only to class and subclass in TypeScript?

April 26, 2022 - 5 min read

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 😃!

Feel free to share if you found this useful 😃.