Design Pattern: Singleton Pattern in TypeScript

Singleton pattern generates and returns the same single instance of a class, in any case. No matter how we generate the instance and how many times we generate it, the same single instance will be returned.

This article discusses the Singleton pattern implementation in TypeScript. Let’s check the details of the implementation step-by-step.

Implementation

Singleton pattern implementation in TypeScript is very similar to other object-oriented programming languages(like Java). Here are the key points that we need to follow while implementing the Singleton pattern in TypeScript:

  • Create a class for the Singleton implementation.
  • Declare a “static” property for storing the instance of the same class.
  • Make the constructor “private” so that a new class instance can not be created using the “new” keyword.
  • Create a “static” function for getting an instance of the class. In the function check if an instance already exists or not. If an instance exists then return that. And if the instance does not exist, then create a new instance, assign it to the instance variable, and then return that.

Here is a simple and basic example of Singleton pattern implementation in TypeScript.

class Singleton {
    // Make sure to make the "private" and "static"
    private static singletonInstance: Singleton;

    // Make sure to make the constructor "private"
    private constructor() {

    }

    // Make sure to make the function "static"
    static getInstance(): Singleton {
        // Check if an instance already exists
        if (!Singleton.singletonInstance) {
            // If instance does not exist then create an instance
            // and assign that to "singletonInstance"
            Singleton.singletonInstance = new Singleton();
        }

        // Return the "singletonInstance"
        return this.singletonInstance;
    }
}


// Use the singleton implementatin like below
const mySingletonInstance = Singleton.getInstance();

// New instance can not be created using the "new" keyword
// as the constructor is declared as "private".
// An attempt like below will generate error
// const someSingletonInstance = new Singleton(); 

Examples

Here are a few examples of the Singleton pattern implementation in TypeScript.

Example #1: Database Connection

Let’s take the example of creating a class for database connection.

Singleton Class

To create the Singleton class follow these points –

  • Create a file named “db-conn-singleton.ts”.
  • In the file create a class named “DbConnSingleton”.
  • In the class declare a property named “singletonInstance” of type “DbConnSingleton”(same as the class). Make sure to make this property “private static”.
  • Declare some properties required for storing connection information, like “host”, “port”, “username”, and “password”. These properties are declared as “readonly” here, we are only going to set these in the constructor.
  • Create a constructor, and make it “private”. Accept params for the values of “host”, “port”, “username”, and “password”. Set the values in the constructor.
  • Declare a function named “getInstance”. Make this “static”, and accept params for “host”, “port”, “username”, and “password”.
  • In the “getInstance” function check if an instance is already created, by checking if the value of “singletonInstance” already exists or not. If it does not exist then create a new instance of the “DbConnSingleton” class and assign that to the “singletonInstance” property. At the end return the “singletonInstance”.
  • Create some utility functions as per requirement. We have created some dummy functions here – “printConnectionDetails” and “executeQuery”.
// db-conn-singleton.ts

class DbConnSingleton {
    // Declare a private static property, required for the Singleton implementation
    private static singletonInstance: DbConnSingleton;

    // Some properties for storing some information
    // These properties can be declared as readonly if needed
    private readonly host: string;
    private readonly port: number;
    private readonly username: string;
    private readonly password: string;

    /**
     * Constructor
     * 
     * Make sure to make it private for the Singleton implementation
     */
    private constructor(host: string, port: number, username: string, password: string) {
        this.host = host;
        this.port = port;
        this.username = username;
        this.password = password;
    }

    /**
     * Make sure to declare the function as "static" for the Singleton implemenation
     */
    static getInstance(host: string, port: number, username: string, password: string): DbConnSingleton {
        // Check if instance is already created or not
        if (!this.singletonInstance) {
            console.log('Creating new db connection instance');

            this.singletonInstance = new DbConnSingleton(host, port, username, password);
        }

        return this.singletonInstance;
    }

    // Dummy utility function
    public printConnectionDetails() {
        console.log("host:" + this.host);
        console.log("port:" + this.port);
        console.log("username:" + this.username);
        console.log("password:" + this.password);
    }
    
    // Dummy utility function
    public executeQuery(query: string) {
        console.log("Executing query: " + query);
    }

}

export default DbConnSingleton;

Demo

To use the Singleton implementation use the steps below.

  • Create a file named “demo.ts”.
  • Create an instance by using “DbConnSingleton.getInstance(……….)”. Provide the param values for “host”, “port”, “username”, and “password”.
  • Try to create another instance by using the same process, and pass some different param values.

After the creation of the instances, we can see that both instances are the same. Param passed in the second attempt are not affecting, as the previous instance is returned then.

// demo.js

import DbConnSingleton from "./db-conn-singleton";

// Create on instnce
const dbConnOne = DbConnSingleton.getInstance('loclahost', 1234, 'root', 'secret!pass');

// Print details of the first instance
console.log("DB connection details for dbConnOne:");
dbConnOne.printConnectionDetails();

// Attempt to create another instance
const dbConnTwo = DbConnSingleton.getInstance('192.168.55.55', 2222, 'root2', 'secret!pass2');

// Print details
console.log("DB connection details for dbConnTwo:");
dbConnTwo.printConnectionDetails();

// Both will print the same details
// as both are same instance

Output

Above demo code will generate the below output.

Creating new db connection instance

DB connection details for dbConnOne:
host:loclahost
port:1234
username:root
password:secret!pass


DB connection details for dbConnTwo:
host:loclahost
port:1234
username:root
password:secret!pass

Source Code

Use the following link to get the source code:

Other Code Implementations

Use the following links to check Singleton pattern implementation in other programming languages.

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.