Skip to content
tezvyn:
Menu

Implementing the Singleton pattern in TypeScript

Source: interviewHardHow cards are made

Summary

Encapsulating single-instance access.

Key points

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.

Interview question

What role does the private constructor play in a TypeScript Singleton implementation?

  • a.It guarantees thread safety across concurrent getInstance calls
  • b.It makes the static instance field automatically lazy-loaded
  • c.It prevents external code from using new, forcing access through getInstanceCorrect
  • d.It encrypts the instance so its internal fields cannot be read
Why?

A private constructor blocks new MyClass at compile time, so callers must use the controlled getInstance accessor. It does not encrypt fields, provide thread safety, or by itself make the field lazy.

Just read this? Test yourself on what you have been reading.

Read the original → refactoring.guru

Put your scrolling time to good use

Learn one idea, try a quiz and save useful cards for revision. Tezvyn makes it easy to learn and stay current in your tech field, a few minutes at a time.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on typescript — each one lists the topics its interview covers.

See open roles