How to improve React component type-safety with Typescript generics?

How to improve React component type-safety with Typescript generics?

Henrikas Jasiūnas

Senior Software Engineer


While a big part of the front-end development community has embraced Typescript, not many developers take full advantage of the benefits that it provides. One of such underutilized features, without a doubt, is generics. The concept of generic types isn’t an easy one to wrap your head around, but once you’ve understood its power, you’ll be able to take your components to the next level by making them more flexible, reusable, and maintainable. In this blog post, we’ll take a close look at a specific example of how to improve the type-safety of a React component by using Typescript generics.

The problem

To demonstrate the problem, let’s make a custom select dropdown. Usually, components of this kind contain some extra logic and/or styling, but in our case, it simply wraps a native HTML select element:

As you might expect, it has value, options,and onSelect props, and we are using a string type for the value. Let’s include this component into our App.tsx:

Now we need some data to pass to our component. For the options, we’ll take values of an enum, and the selected option value will be set in the component state:

And finally, when the onChange event is emitted, we want to set the selected option as the value from the event emitter. But as we do that, we run into a Typescript problem:

Even though all the options that we pass to our SelectDropdown component have the same value type as selectedPlatform, we cannot assign a value to it from onChange because it’s typed as a string:

The solution

Now let’s take a look at how a developer would likely deal with this kind of issue. The easiest and most straightforward thing to do here is, of course, to simply use any instead of string in the onChange:

“Voila, the job is done – not a single Typescript error in sight!“.

However, one of the first things everyone should learn about Typescript is that using any is a risky practice that should be reserved for those rare cases when no other option is available. Let’s try to find a better way.

Another common approach to dealing with such issues is by using type casting:

The error is fixed! However, while casting is not as bad as any, it is still not type-safe and can lead to errors. Consider the following example: