Private & Protected Constructors in TypeScript

Constructors are important in creating objects within classes while using TypeScript, in this by default constructors are public and thus can be called from any location. At times though, you may want to stop any other person from creating instances of your class – that is where we come across private and protected constructors.

Understanding Constructors in TypeScript

In TypeScript a constructor is a method in a class that gets triggered when an instance of it is created and is usually utilized to set the member properties of the object.

Example: In this example, the default constructor is public permitting the instantiation of Example from any location.

JavaScript
class Example {
  constructor(public name: string) {
    this.name = name;
  }}
const example = new Example('TypeScript');
console.log(example.name); 

Output:

TypeScript

Private Constructors

You can use a private constructor to create a class which cannot be instantiated from outside that class most especially when implementing the Singleton pattern or when you plan on making a class static.

Singleton Pattern

In this musing pattern, we make sure that there is one and only one object for a certain class instance as well as create an access point for this instance.

Example: In this use case, Singleton possesses a private constructor whose purpose is to prohibit direct instantiation whereas a way to get the one and only instance of the class is through the use of the function getInstance.

JavaScript
class Singleton {
    private static instance: Singleton;

    private constructor() {
        // Private constructor ensures external
        // code cannot instantiate this class
    }

    public static getInstance(): Singleton {
        if (!Singleton.instance) {
            Singleton.instance = new Singleton();
        }
        return Singleton.instance;
    }

    public showMessage(): void {
        console.log('Hello, Singleton!');
    }
}

const singleton1 = Singleton.getInstance();
const singleton2 = Singleton.getInstance();

singleton1.showMessage();
console.log(singleton1 === singleton2); 

Output:

Hello, Singleton!
true

Static Class

An instance of a static class cannot be created and mostly includes static members.

Example: That is to say a private constructor here guarantees that instances of Utility cannot be created so that it becomes a static class with just static methods.

JavaScript
class Utility {
    private constructor() {
        // Prevent instantiation
    }

    public static logMessage(message: string): void {
        console.log(message);
    }
}
Utility.logMessage('This is a static method.'); 

Output:

This is a static method.

Protected Constructors

When you want to create a base class, which should not be instantiated directly but allows subclassing, a protected constructor will restrict the instantiation of a class from outside the class and its subclasses.

Example: In this example the class Base has a protected constructor that makes it possible for it to be subclassed but not directly instantiated, derived class can invoke the Base constructor by calling super.

JavaScript
class Base {
  protected constructor(public name: string) {
    this.name = name;
  }
}

class Derived extends Base {
  constructor(name: string) {
    super(name);
  }

  public showName(): void {
    console.log(this.name);
  }
}

const derived = new Derived('TypeScript');
derived.showName(); 

// const base = new Base('Base');
// Error: Constructor of class 'Base' is protected
// and only accessible within the class declaration.

Output:

TypeScript

Use Cases

When to Use Private Constructors

  • Singleton Pattern: Ensures a class has only one instance.
  • Static Classes: Prevent instantiation and also it provide only static methods.

When to Use Protected Constructors

  • Abstract Base Classes: Prevent direct instantiation so subclasses can be created.
  • Controlled Instantiation: The base class includes methods which can be employed by the subclasses to guarantee their instantiation logic is well managed.

Conclusion

Class instantiation in Typescript can be controlled using private as well as protected constructors. By means of these access modifiers, one can enforce patterns like singleton or static classes and define abstract base classes, by understanding these concepts it improves the ability to come up with strong TypeScript programs that are easy to manage.



Contact Us