Private, Public & Protected Access Modifiers in TypeScript

Private, Public & Protected are the Access Modifiers that we can use in Typescript to control whether certain methods or properties are visible to code outside the class. In this tutorial, let us learn about the similarities and differences between them.

Public

Public access modifier allows the class properties and method freely accessible anywhere in the code. The public is the default access modifier if we do not specify the access modifier

In this example, the Person class has two properties firstName & lastName. It also contains a method getName. All of them are prefixed with the keyword public. As you can see we can access all of these properties outside the class.

class Person {
  public firstName:string;
  public lastName:string;
 
  constructor(firstName:string, lastName:string) {
    this.firstName=firstName;
    this.lastName=lastName;
  }

  getName() : string {
    return this.firstName + " "+ this.lastName
  }
} 

let p= new Person("Jon","Snow")


console.log(p.firstName)   //Jon
console.log(p.lastName)    //Snow
console.log(p.getName())      //Jon Snow

The above code works even if we remove the keyword public. Because it is the default access modifier.

Private

The Private access modifier restricts access to the class member from within the class only. We cannot access the property or the method from outside the class

In this example, we mark both firstName & lastName as Private. When we try to access them outside the class we get the compiler error Property 'firstName' is private and only accessible within class.

class Person {
  private firstName:string;
  private lastName:string;
 
  constructor(firstName:string, lastName:string) {
    this.firstName=firstName;
    this.lastName=lastName;
  }

  getName() : string {
    return this.firstName + " "+ this.lastName
  }
} 

let p= new Person("Jon","Snow")

//Compiler Error
console.log(p.firstName)   //Property 'firstName' is private and only accessible within class 'Person'.
console.log(p.lastName)    //Property 'lastName' is private and only accessible within class 'Person'

//ok
console.log(p.getName())   //Jon Snow

We cannot even access the private property in a derived class. In this example, the Employee class extends the Person class. The changeName method of the Employee class tries to access the firstName & lastName of the Person class. The compiler throws the Property is private and only accessible within class 'Person' error.

class Person {
  private firstName:string;
  private lastName:string;
 
  constructor(firstName:string, lastName:string) {
    this.firstName=firstName;
    this.lastName=lastName;
  }

  getName() : string {
    return this.firstName + " "+ this.lastName
  }
} 


class Employee extends Person {
  designation:string;

  constructor(firstName:string, lastName:string, designation:string) {
    super(firstName,lastName)
    this.designation=designation;
  }

  changeName(firstName:string, lastName:string): void {

    //ERROR 
    
    this.firstName=firstName;  //Property 'firstName' is private and only accessible within class 'Person'.
    this.lastName=lastName;   //Property 'lastName' is private and only accessible within class 'Person'.
  }

}


let p= new Employee("Jon","Snow","Manager")

//Compiler Error
console.log(p.firstName)   //Property 'firstName' is private and only accessible within class 'Person'.
console.log(p.lastName)    //Property 'lastName' is private and only accessible within class 'Person'

//ok
console.log(p.getName())   //Jon Snow

Protected

The Protected modifier allows access to the class member from itself and from any classes that inherit (sub-class) from it.

In this example, we have marked the firstName & lastName as Protected. We are able to modify these properties in the changeName method of the derived class Employee.

But accessing these members in the instance created using the Person class or using the Employee class results in a compiler error.

class Person {
  protected firstName:string;
  protected lastName:string;
 
  constructor(firstName:string, lastName:string) {
    this.firstName=firstName;
    this.lastName=lastName;
  }

  getName() : string {
    return this.firstName + " "+ this.lastName
  }
} 


class Employee extends Person {
  designation:string;

  constructor(firstName:string, lastName:string, designation:string) {
    super(firstName,lastName)
    this.designation=designation;
  }

  changeName(firstName:string, lastName:string): void {

    //Ok
    this.firstName=firstName;
    this.lastName=lastName;  
  }

}


let p= new Employee("Jon","Snow","Manager")

//Compiler Error
console.log(p.firstName)   //Property 'firstName' is private and only accessible within class 'Person'.
console.log(p.lastName)    //Property 'lastName' is private and only accessible within class 'Person'

//ok
console.log(p.getName())   //Jon Snow


let p1= new Person("Jon","Snow")
//Compiler Error
console.log(p.firstName)   //Property 'firstName' is private and only accessible within class 'Person'.
console.log(p.lastName)    //Property 'lastName' is private and only accessible within class 'Person'

Overriding Access Modifier in the Derived Class

The derived class can redeclare the property and override the Access modifier. In the example, the derived class Employee re-declares the protected property firstName & lastName. This effectively removes the protected protection from the objects created using the Employee class. But the objects created using the Person class will not be able to access the firstName & lastName

class Person {
  protected firstName:string;
  protected lastName:string;
 
  constructor(firstName:string, lastName:string) {
    this.firstName=firstName;
    this.lastName=lastName;
  }

  getName() : string {
    return this.firstName + " "+ this.lastName
  }
} 


class Employee extends Person {
  firstName:string;
  lastName:string;
  designation:string;

  constructor(firstName:string, lastName:string, designation:string) {
    super(firstName,lastName)
    this.firstName=firstName;
    this.lastName=lastName;    
    this.designation=designation;
  }

  changeName(firstName:string, lastName:string): void {
   this.firstName=firstName; 
    this.lastName=lastName;   
  }

}

//Created from the Employee Class
let e= new Employee("Jon","Snow","Manager")

//Ok
console.log(e.firstName)
console.log(e.lastName) 


//Created from the Person class
let p= new Person("Jon","Snow")

//Error
console.log(p.firstName)  //Property 'firstName' is protected and only accessible within class 'Person' and its subclasses.
console.log(p.lastName)   //Property 'lastName' is protected and only accessible within class 'Person' and its subclasses.

Readonly Vs Public, Private & Protected

The ReadOnly keyword makes the property read-only. That is you can only initialize it either when you declare it or inside the constructor function. Assigning any value to the readonly property anywhere else results in an error. But it does not prevent you from accessing it. It only prevents you from assigning a value.

Private & Protected prevents you from accessing the variable itself.

We can mix and match both. In this example we mark firstName & lastName as both protected and read-only. We can access the property in the changeName method the derived class Employee. But we cannot modify it because it is protected.

class Person {
  protected readonly firstName:string;
  protected readonly lastName:string;
 
  constructor(firstName:string, lastName:string) {
    this.firstName=firstName;
    this.lastName=lastName;
  }

  getName() : string {
    return this.firstName + " "+ this.lastName
  }
} 


class Employee extends Person {
  designation:string;

  constructor(firstName:string, lastName:string, designation:string) {
    super(firstName,lastName)
    this.designation=designation;
  }

  changeName(firstName:string, lastName:string): void {

    //You cann access the property
    console.log(this.firstName)
    console.log(this.lastName)

    //Error Property is readonly. You cannot modify it
    this.firstName=firstName;  //Cannot assign to 'firstName' because it is a read-only property.
    this.lastName=lastName;    //Cannot assign to 'lastName' because it is a read-only property.
  }

}


let p= new Employee("Jon","Snow","Manager")

//Compiler Error. Cannot access becuase it is protected
console.log(p.firstName)   //Property 'firstName' is private and only accessible within class 'Person'.
console.log(p.lastName)    //Property 'lastName' is private and only accessible within class 'Person'

Optional Property

You can also make the property Optional along with the access modifier and readonly keyword.

class Person {
  protected firstName?:string;
  protected readonly lastName?:string;
 
  constructor(firstName:string, lastName:string) {
    this.firstName=firstName;
    this.lastName=lastName;
  }

  getName() : string {
    return this.firstName + " "+ this.lastName
  }
} 

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top