Singleton Decorator

Volodymyr Yepishev - Jul 1 '22 - - Dev Community

It turns out it's actually possible to apply singleton pattern using decorators in typescript.

Since decorator is essentially a wrapper-function, we can use it to return a fake anonymous class and use its constructor
to trap an instance of the decorated class in a closure variable, which we can reuse later when somebody tries to invoke
the class constructor again:

function Singleton<T extends new (...args: any[]) => any>(ctr: T): T {

    let instance: T;

    return class {
        constructor(...args: any[]) {

            if (instance) {
                console.error('You cannot instantiate a singleton twice!');
                return instance;
            }

            instance = new ctr(...args);
            return instance;
        }
    } as T
}
Enter fullscreen mode Exit fullscreen mode

Now we can use it to decorate any class to make it a singleton:

@Singleton
class User {
    constructor(private name: string) { }

    public sayName(): void {
        console.log(`My name is ${this.name}`);
    }
}

let user = new User("Bob");
let secondUser = new User("not Bob");
user.sayName(); // "Bob"
secondUser.sayName(); // still "Bob"
Enter fullscreen mode Exit fullscreen mode

Playground

Interesting, eh?

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .