DEV Community

Cover image for Typescript Generics explained in 2 minutes
Nicky Christensen
Nicky Christensen

Posted on

Typescript Generics explained in 2 minutes

TypeScript is powerful, it can make your code a lot more stable, readable, easier to refactor and so much more.

TypeScript has Generics which are super useful when wanting to write clean and reusable pieces of code. Generics offer a way for developers to create reusable code and it works in a way to make components work with any data type and not be restricted to a single data type.

Given that you are in this article, I’m expecting you already know the basics of TypeScript, and want to know more about Generics in TypeScript so I won't go deep into an explanation around TypeScript itself.

Consider the following code:

let courses = [];
const fetchCourseTemplates = async () => {
  isLoading = true;
  const companyId = '123';
  try {
    courses = await getAllDocuments(`course_templates/${companyId}/templates`);
    isLoading = false;
  } catch (e) {
    isLoading = false;
    throw new Error('Cant load templates: ' + e);
  }
};
Enter fullscreen mode Exit fullscreen mode

The function we are calling will look like this:

// Our reuseable function to get data
export const getAllDocuments = async (collectionName: string) => {
  const documents = [];
  const querySnapshot = await getDocs(collection(db, collectionName));
  querySnapshot.forEach((doc) => {
    const data = doc.data();
    documents.push({
      id: doc.id,
      ...data
    });
  });

  return documents;
};
Enter fullscreen mode Exit fullscreen mode

With the above code, you are fetching some data from an API, passing a parameter on where to fetch the data (In this case, a reference to a collection in Firebase). The data passed back from the function are stored in a variable. All good, right?

Not quite. You see, if you have a reusable function to fetch data from a collection, you never know which type of data you are actually getting back. Well, you may know now but TypeScript doesn’t.

Imagine you are using this function to retrieve all kinds of different documents from different places in Firebase, the data you get returned will most likely be different from time to time. So how do we make TypeScript happy?

Introducing Generics

Generics will help you in this case. You can extend the function to use generics, and when calling the function, you specify which type of data you are working with. This will make TypeScript understand.

Let’s take the above code and see how it would look using Generics.

let courses: Course[] = [];
const fetchCourseTemplates = async () => {
  isLoading = true;
  const companyId = '123';
  try {
    courses = await getAllDocuments<Course>(`course_templates/${companyId}/templates`);
    isLoading = false;
  } catch (e) {
    isLoading = false;
    throw new Error('Cant load templates: ' + e);
  }
};
Enter fullscreen mode Exit fullscreen mode

The main difference here is in the await. You might notice the . This is basically me passing a type to the function, telling TypeScript what data the function should work with. Let's take a look at the next function

// Our reuseable function to get data
export const getAllDocuments = async <T>(collectionName: string) => {
  const documents: T[] = [];
  const querySnapshot = await getDocs(collection(db, collectionName));
  querySnapshot.forEach((doc) => {
    const data = doc.data();
    documents.push({
      ...data
    } as T);
  });

  return documents;
};
Enter fullscreen mode Exit fullscreen mode

Notice after the async keyword, I do . This is me getting the type back I called the function with. Further down, you will see that the array I’m creating should be of the type I passed on (We passed Course). When we are returning, TypeScript now knows that I’m returning whatever type I provided. In our cases, it would return an array of courses, because we passed Courses as our type in the fetchCourseTemplates function.

That about wraps it up! I hope you understood the above.
Of course, there is a lot more to generics and many more use cases than what I just showed, but hopefully, it gave you a basic understanding and you can see why it is powerful.

If you’d like to catch up with me sometime, follow me on Medium | Twitter | LinkedIn or simply visit my website (That is in Danish)

Top comments (0)