The magic of Generic functions and Type Inference in TypeScript

Max Shahdoost
4 min readSep 2, 2023

--

Generic Function Inference

Generics are one of the most necessary parts of TypeScript and without them, I can say it was not worth using TypeScript at all!

In this article, I am going to cover one of the trickiest parts of generic type use cases which is very powerful once you can understand it and put it in use for yourself. Let’s begin with a problem-solving approach.

The problem?!

Imagine you have a store like below using the famous Zustand State Management Library.

A simple store in Zustand

It is possible to pick everything you want in a one-line code, for instance, if I wanted to pick newConversationId from the state.

Selecting state values like a normal selector function

But I really don’t like that approach! why should we write multiple useConversationStore hooks to access multiple values? why not just declare a single hook that can give us all that information based on what we want?

By far Zustand gives us a good practice approach to fix the above issue but it has caveats!

Refactored Zustand store to access multiple items from the store

In the above picture, I refactored our store to use the approach they offered in their documentation, The problem is that we need to pass shallow every time we would like to use the new approach, and that creates a problem of its own and is against DRY principles since we want to make everything as reusable as possible.

The below code snippet is the first attempt to solve the problem but the moment you start using it you will find some problems, You need to pass the keys in the param array keyswhich is not aware of the keys you’ve already passed, in return it also doesn’t know which items you asked for and which not so it is really dangerous since it gives you nothing about the I/O of the function.

A not good approach to fix the issue!

Solution? Generic Function + Type Inference is a powerful setup!

We need to create a better hook to do the job for us, We pass the arguments we want in a callback and we receive the desired store properties in return.

Generic function T and inference of the return value in runtime!

Above is an example of the combination we are looking for to solve our problem, someFunction recives a generic type of <T> and the argument fn which is a callback function also returns <T> So from the TypeScript perspective, we need to explicitly declare the T type when we are going to use the someFunction But that is not true!

For instance, the res in the above code holds the result value of the function and when we don’t pass any type explicitly for <T> its type will try to infer the type <T> from the runtime values passed and returned from the callback. This is the magic of TypeScript generic inference.

Now let’s refactor our store code

Generic Function + Inference in our store

Congratulations, now we have a custom hook and it is returning the desired states from a store in a custom form as we would like, for example in an object or array destructring like the above.

Thank you for reading. If you’ve liked this article, one of the best ways to support me is to share it. Should you have any questions or comments, you can always contact me via LinkedIn. I’ll be more than happy to help you out with your queries.

--

--

Max Shahdoost

A highly passionate and motivated Frontend Engineer with a good taste for re-usability, security, and developer experience.