# Singleton Pattern in TypeScript

Source: https://tpiros.dev/blog/singleton-pattern-in-typescript

Design patterns help us write better software. Full stop.

# GoF

Back in 1994, Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides published _Design Patterns: Elements of Reusable Object-Oriented Software_. You might know the authors as the Gang of Four (GoF).

The 23 patterns they outlined still hold up. They form a solid base for modern software development, and they're just as applicable now as they were then.

# Design Pattern types

Design patterns break down into categories based on what they aim to achieve:

- Creational: deal with object creation
- Structural: deal with relationships between objects (or other entities)
- Behavioural: deal with communication patterns between objects
- Concurrency: deal with multi-threaded paradigms

# Singleton Pattern

The Singleton is a creational pattern. It guarantees a class has only one instance (a single unique copy) and provides a global access point to that instance.

## When to use the singleton pattern?

Some situations demand exactly one instance. Working with a shared resource is the classic example. A single entry point means fewer bugs, because no competing instances can step on each other.

## TypeScript implementation

You could implement the Singleton in any language, vanilla JavaScript included. But let's see what it looks like in TypeScript.

> It goes without saying that should you want to get the JavaScript implementation, just transpile the TypeScript code to JavaScript, either to ES2015 or to ES5.

## Singleton example

Here's a practical example. We want a class that tracks temperature. The system should have exactly one entry point for altering that temperature. Here's the Singleton:

```typescript
class Singleton {
  private static instance: Singleton;
  private _temperature: number;
  private constructor() {}
  static getInstance() {
    if (!Singleton.instance) {
      Singleton.instance = new Singleton();
      Singleton.instance._temperature = 0;
    }
    return Singleton.instance;
  }
  get temperature(): number {
    return this._temperature;
  }
  set temperature(score) {
    this._temperature = score;
  }
  increaseTemperature(): number {
    return (this._temperature += 1);
  }
  decreaseTemperature(): number {
    return (this._temperature -= 1);
  }
}
```

A few things to notice:

- The constructor uses the `private` access modifier, so you can't instantiate the class with `new`.
- `getInstance()` checks whether an instance exists. If not, it creates one. Either way, it returns the instance.

Try instantiating with `new`:

```typescript
const myInstance = new Singleton(); // Constructor of class 'Singleton' is private and only accessible within the class declaration.
```

Error. The only way in is through `getInstance()`:

```typescript
const myInstance = Singleton.getInstance();
console.log(myInstance.temperature); // 0
```

We can access the temperature property. Let's set it and bump it around:

```typescript
console.log((myInstance.temperature = 25)); // 25
console.log(myInstance.increaseTemperature()); // 26
console.log(myInstance.increaseTemperature()); // 27
console.log(myInstance.decreaseTemperature()); // 26
```

Think about what would happen if we could create a second instance. We'd be able to overwrite the temperature readings.

But calling `getInstance()` again doesn't create a new instance. It spots the existing one and returns it. The temperature value carries over:

```typescript
const myInstance2 = Singleton.getInstance();
console.log(myInstance2.temperature); // 26
```

Compare the two and you get `true`, because they're the same object:

```typescript
console.log(myInstance === myInstance2); // true
```
