Bits and Pieces

Insightful articles, step-by-step tutorials, and the latest news on full-stack composable software development

Follow publication

The Singleton Pattern In TypeScript

What is the Singleton pattern and when to use it.

Fernando Doglio
Bits and Pieces
Published in
7 min readJan 19, 2021

--

Image by Myriams-Fotos from Pixabay

Design patterns in general, allow for developers to use pre-defined and proven templates to structure a logical solution to a type of problem.

There are a lot of design patterns available and huge books for you to read up on them. Some of these patterns can be quite confusing, while others, very intuitive, so much so that sometimes you’ll find out you’ve been implementing a pattern without even know about it.

And in particular, the Singleton pattern is probably one of the most common patterns out there, it’s not specifically complex and it’s a great way to get started with them.

What is the Singleton pattern?

The singleton pattern is a way to structure your code so that you can’t have more than one instance of your logic, ever.

In case it wasn’t obvious yet, these patterns are meant for the Object-Oriented Programming paradigm. This means that the above sentence can be translated to:

By implementing a singleton we can ensure we only have one instance of our class, ever.

As you’re about to see, Typescript has all the required tools for us to actually ensure that the above statement is 100% true.

Implementing Singleton on TypeScript

The implementation is simple, but we do have to ensure there is no way for a user to instantiate twice our class. And how can we do that? By default the new keyword creates a new instance, and we can’t override that behavior.

The solution, has two parts:

  1. On one side, we need to provide a new way of instantiating our class. That way, we can control how and when that happens.
  2. On the other, we also need to keep developers from using the new keyword on us.

The first part can be achieved by adding a static method and a static property to our class. Remember, static members — also known as class-level members — don’t need an instance of the class to be used. In fact, they don’t recognize the instance at all.

And the second part can be achieved by “hiding” the constructor of our class by making it private. With that, you won’t be able to create a new instance, since the constructor method, which is implicitly called when you use the new keyword, won’t be accessible to you from outside the class.

Let’s take a look at a quick example:

Notice how I said “from outside the class”, since the constructor is private, it can be used from inside it (inside the getIntance method).

If you tried to instantiate this class, you’d get the following error:

You can use it, however, like this:

The output would be:

constructor called!
my logic!

Tip: Build with independent components, for speed and scale

Instead of building monolithic apps, build independent components first and compose them into features and applications. It makes development faster and helps teams build more consistent and scalable applications.

OSS Tools like Bit offer a great developer experience for building independent components and composing applications. Many teams start by building their Design Systems or Micro Frontends, through independent components.
Give it a try →

An independently source-controlled and shared “card” component. On the right => its dependency graph, auto-generated by Bit.

What problems does Singleton solve?

What’s the use of having a class that can only be instantiated once? Really, it sounds like an anti-pattern to be honest, but it’s not!

It’s actually a very clever way of solving a very simple problem: keeping a single channel of communication with an outside resource open all the time.

Singletons are the OOP equivalent of global variables. We’re all taught not to use them when we’re learning, because a global variable can be modified without us knowing about it. But damn, they were useful when we had to keep track of a piece of data common to multiple functions.

The same goes for Singletons, only that instead of dealing with a primitive value, we’re dealing with a potentially complex object, one that can provide a strong and hard-to-mess-up API for developers to use without the worry of side-effects.

So let me ask you again, what exactly are we solving by implementing this glorified global variable?

Well, there are some use cases where one might argue, a Singleton comes in handy:

  • If you’re trying to keep resource utilization under control. By centralizing your information flow on a single instance, you can perfectly control how much data goes into and comes out of an external resource. Be it a single file, a database connection or a printer spool. In all cases, having a single instance of your interface to the resource gives you absolute control over it.
  • Logging. We’ve all done it, adding logs throughout your code is usually a must, especially for big projects. Enabling, disabling them and even changing their default level can be a pain if you don’t centralize the code in a single entity — i.e “the logger”. By having your logger be a singleton, you ensure only one in-memory instance of it is recording your data (instead of accidentally instantiating several at once, and having them sending repeated messages).
  • Caching. An in-memory cache can be implemented using a singleton. If you think about it, it fits: you don’t want to have multiple instances of it, you need a centralized and easy way of accessing it. This is definitely a viable use case.

The pattern itself is simple enough, but the utility it provides can be of great use in some situations.

Of course, because this is the real world, there are also some downsides to the pattern, and some people tend to hate on our good old friend Singleton because of them. So before the angry comments start flowing in, let me also show you the dark side of the Singleton.

Why would you avoid Singletons?

Everything has a downside, whether you think it applies to your use case or not, there is a dark side to every piece of technology out there.

And the Singleton is no different. So what’s wrong with the Singleton pattern?

  • It breaks the Single Responsibility Principle. Not a big deal, unless of course, you’re into principles. Essentially the SRP says every class should only take care of one thing and one thing alone, and the Singleton is taking care of two things: ensuring there is only one instance of itself, and the actual logic it was designed to hold.
  • Bad memory management. Yeah well, who needs memory anyway, if you’re using Firefox, a little Singleton won’t make a difference! Truth be told, Singletons live in your memory for pretty much… well, forever, or until your code dies anyway. Is it a bad thing? It definitely depends, we’re literally talking about a single instance of a class. How big is your class to turn that into a problem? Or let me ask you the opposite question: how small is your memory that you’re worried about a single instance of a class? There are probably a few scenarios where this might be a problem, but the browser ain’t one of them.
  • By using singletons, your classes are hiding dependencies. Big systems where there are lots of dependencies and huge test suites might not like how singletons can play against them. Remember how I said that Singletons are essentially a glorified global variable? Well, if you use them like that in your classes, then when you need to test your code, you’re literally hiding an external dependency that you won’t be able to overwrite easily.
  • You can’t really extend a Singleton. I mean, why would you? That’s the main question. A Singleton is meant to be unique, not extended — and the fact that we’re using static methods and a private constructor makes things a lot harder in that department — . But suppose you want a way to turn a class into a Singleton, well in that case your only chance is with an interface, which lucky for you, TypeScript supports. That way, the moment you declare that your class needs to implement the Singleton interface, you’ll be forced to provide the proper methods.

I’m sure you can think of a couple more, but you get the point, there is no perfect pattern out there, just like there is no perfect ice cream flavor — except for lemon, but that’s another topic.

Is Singleton the best pattern out there? Not by a long-shot. Is it the worst? Nope! there are definitely some very valid use cases for this pattern and used with care, it can provide great value.

But just like with any pattern, library or IF statement you write, if you don’t think and plan ahead, your code will turn into spaghetti, no matter how many patterns you add to it.

What about you? Are you pro or against the Singleton? Leave a comment below and share your thoughts on this pattern.

Learn More

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Published in Bits and Pieces

Insightful articles, step-by-step tutorials, and the latest news on full-stack composable software development

Written by Fernando Doglio

I write about technology, freelancing and more. Check out my FREE newsletter if you’re into Software Development: https://fernandodoglio.substack.com/

Responses (3)

Write a response