Implementing the Singleton pattern in TypeScript
Encapsulating single-instance access.
Private constructor blocks new, a static private instance field caches it, static getInstance lazily creates and returns the one instance.
WHAT THIS TESTS Whether you can use TypeScript's compile-time access modifiers to enforce a single instance, and whether you understand the design downsides of the pattern, not just the mechanics.
A GOOD ANSWER COVERS Three pieces work together. The constructor is marked private so no external code can write new MyClass, which TypeScript rejects at compile time. A static private field, often instance, holds the one created object. A public static getInstance method checks whether instance is set; if not it constructs it once and stores it, then returns the cached instance on every subsequent call. This gives lazy, controlled, global access to exactly one object. A senior answer also names the costs: a singleton is hidden global state that makes unit tests order-dependent and hard to mock or reset, can mask dependencies, and is often better replaced by a single instance supplied through dependency injection.
COMMON WRONG ANSWERS Leaving the constructor public, so callers can still make extra instances. Forgetting to cache, recreating the object each call. Using a mutable public static field directly. Claiming singletons are always the right choice and ignoring testability. Assuming TypeScript private gives runtime privacy; it is compile-time only unless using ECMAScript hash-private fields.
LIKELY FOLLOW-UPS How do you reset or mock a singleton in tests? Is TypeScript private enforced at runtime? How does a module-level const compare, since ES modules are singletons already? Any thread-safety concerns in Node?
ONE CONCRETE EXAMPLE class Config { private static instance: Config; private settings = loadSettings(); private constructor() {} static getInstance(): Config { if (!Config.instance) { Config.instance = new Config(); } return Config.instance; } } Now Config.getInstance() always returns the same object, and new Config() fails to compile. In practice, because an ES module is itself evaluated once, exporting export const config = new Config() achieves the same single instance with less ceremony, which is worth raising.
Read the original → refactoring.guru
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.