JavaScript design patterns #2. Factories and their implementation in TypeScript

JavaScript

As discussed in the previous part of this series, there are many design patterns out there. Some of them fit well into the JavaScript language, and they are often used. In this article, we discuss the factory method pattern and show some of its use-cases. We also implement it in TypeScript.

There seems to some confusion regarding what the Factory pattern in JavaScript is. Let’s try to look up the “JavaScript factory” term in the search bar.

Factory functions

One of the approaches that might come up are the factory functions.

The job of a factory function is to return an object. It might be an alternative to creating classes. A useful addition to those are mixins that you can use to make some parts of your factory functions reusable.

We might achieve a similar outcome with the use of classes and inheritance. Also, major libraries and frameworks such as Angular and React adopted classes. Still, it might be worthwhile to get familiar with the above approach. Especially because it comes up often when looking into the “JavaScript Factory” term. The factory functions are not our primary focus in this article, though.

Factory method pattern

The Factory Method design pattern is one of the fundamental design patterns and is a part of the “Gang of Four” design patterns. It aims to provide a solution for creating objects without specifying the exact class of the object that is created.

Imagine creating a system for online coding teaching. One of your classes would probably be a teacher.

Looks fine at first glance, but the above approach might prove not to be scalable. If we decide to expand our business to teaching the music also, we might end up with something like this:

As you might see, the Teacher class is getting pretty nasty and would get even worse as we add more teacher types to the existing codebase. A common approach to the above issue is to implement the Factory Method pattern.

In the code above you can see that we can use the TeacherFactory to create any type of teacher. Also, we don’t have to worry about breaking any code when adding a new type.

An advantage of the Factory Method pattern that we might notice when we look at how we call the   function is that the type of an instance can be easily decided at the runtime.

We can also go a bit further and use inheritance to make our classes a bit cleaner.

Thanks to the above, we can delegate some of the common features into a separate class. To make our code more bug-proof, it might be a good idea to throw an error if a wrong type is chosen. Let’s use a switch statement!

With our layer of abstraction, we don’t have to use the actual constructors at all. We can reuse our factory when our application keeps on growing without changing the previous types.

The Factory Method in TypeScript

The Factory Method pattern works very well with TypeScript if we do some neat type-checking.

The catch to implementing the Factory in TypeScript is that we need to specify accurately which properties should go with a particular type of an object. To do so, we can use method overloading.

In the code above, we specify explicitly that when we create a music teacher, we need to pass the properties of a music teacher. Otherwise, the TypeScript compiler would throw an error.

Thanks to proper typing, TypeScript now knows that the  , for example, is an instance of the CodingTeacher class.

error TS2339: Property ‘instrument’ does not exist on type ‘CodingTeacher’.

Summary

In this article, we’ve managed to shed some light on what a factory method pattern is and how it shouldn’t be confused with factory functions. To do the above, we’ve implemented both factory functions and the factory method pattern. We’ve also learned how to use the above pattern with TypeScript. While it might be beneficial and help to keep our code clean, it is essential not to overuse it. If we won’t profit from this level of complexity, or we don’t need to generate instances judging their types during runtime, we might introduce make our code unnecessary complicated. If we watch out for the above issues, the factory pattern might come in handy.

Series Navigation<< JavaScript design patterns #1. Singleton and the ModuleJavaScript design patterns #3. The Facade pattern and applying it to React Hooks >>
avatar
  Subscribe  
newest oldest most voted
Notify of
Tomasz Krzyżowski
Tomasz Krzyżowski

public static getTeacher(type: TEACHER_TYPE, properties: MusicTeacherProperties & CodingTeacherProperties)…
should be probably replaced by
public static getTeacher(type: TEACHER_TYPE, properties: MusicTeacherProperties | CodingTeacherProperties)