This page looks best with JavaScript enabled

React Higher Order Components with TypeScript

 ·  ☕ 4 min read  ·  ✍️ Iskander Samatov

React Higher Order Component witg TypeScript


Some React patterns are trickier to implement in TypeScript than others and require knowing the right approach and utilizing the right TypeScript features. The higher-order component is one such pattern.

In this post, we will explore creating a higher-order component from scratch and dynamically calculating its prop requirements using generics and utility types.

What is a Higher Order Component?

Higher-Order Component (HOC) is a function that takes another component and injects additional properties into it. Think of it as wrapping your component with an extra layer that gives it more functionality.

The purpose of HOCs is often to reuse common logic between components and separate logical and presentational layers. With the introduction of hooks, HOCs took a back seat for the most part. Although you see them less, HOCs are still relevant and have certain advantages over hooks, for example a better compatibility with the class-based components.

A well-known example of a HOC is the withRouter function from the react-router library.

Setting up the HOC

Let’s start by scaffolding our HOC first. We will create a simple HOC that adds timer functionality to our components. Our first iteration will not have strict typing, but we will tighten it up as we progress.

Here’s what the first version of our higher-order component looks like:

HOC Basic

At this point, our HOC is not very typesafe since we set any for the target component’s type. There’s no type checking to make sure the component we pass accepts the props we’re trying to inject.

Now let’s start tightening the type checking.

Adding Generics

Let’s make it so that our HOC only accepts React components and that it expects the same props as the target component. We can use TypeScript generics to enforce these restraints:

HOC Generics

ComponentType is a special type React provides for working with components in TypeScript.

Also, notice our use of generics. We used the T type in several places:

  • We’re setting our parameter type to ComponentType<T>. Now, within the scope of this function, T denotes the props type of the target component.
  • We’re also setting the hocProps type to T to enforce that our HOC component receives the same props as the target.

Thanks to generics, TypeScript can dynamically calculate all of the props our original component accepts and enforce the same restriction for the HOC. You can learn more about generics from TypeScript docs .

Using utility types

Type checking in our HOC is looking good so far. Here’s how we would use it:

HOC In Use

But there’s still one more issue we need to fix. When you put our HOC to use, you get an error from TypeScript:

HOC In Use Error

Earlier, I stated that the HOC should expect the same exact props T as the target component, well that’s not entirely true. Our HOC shouldn’t expect props counter, startTimer, and endTimer because it’s the higher-order component’s job to inject these props in the first place.

We can get around this issue by using the Omit utility type . Using Omit, we can tell the HOC to expect all of the props our target component expects, except for the ones it injects:

Using Omit

We made two more changes to our code:

  • Now our HOC accepts props of type hocProps: Omit<T, "count" | "startTimer" | "endTimer">. Using Omit, we created a new type that expects all of the same props as T except for count, startTimer, and endTimer.
  • Since Omit creates a new type, we had to use a workaround {...(hocProps as T)} to let TypeScript know that we expect the hocProps to be almost identical to T except for the props we omitted.

Now our higher-order component is ready to be used!

Conclusion

In this post, we covered the proper way to write higher-order components in TypeScript. We made our HOC both flexible and safely typed using TypeScript’s generics and utility types. Take a look at my post to learn more about other TypeScript utility types useful for React .

Here’s a link to the code sandbox for this tutorial. Thank you for reading!

If you’d like to get more web development, React and TypeScript tips consider following me on Twitter, where I share things as I learn them.
Happy coding!

Share on

Software Development Tutorials
WRITTEN BY
Iskander Samatov
The best up-to-date tutorials on React, JavaScript and web development.