How to implement a Higher-order component in React with TypeScript
Tags: react, typescript, frontend
Published: 2020-04-10 07:53:33

---
title: "How to implement a Higher-order component in React with TypeScript"
published: true
description: "You probably know how to implement a HoC, but do you know how to write types for one?"
tags: ["react","typescript","frontend"]
canonical_url: https://maxrozen.com/2020/04/10/implement-higher-order-component-react-typescript
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/fiqjmtsndz59csgj645v.jpg
---


You might be thinking:

> "Max - it's 2020! Why are you still using HoCs instead of hooks?!"

to which I'd reply

> "Saying 'It's $CURRENT_YEAR...' is incredibly cliché at this point, and contributes to the JavaScript community's churn. Write boring code."

So anyway, I came across a situation in which I needed to use a React hook in a class-based component. My initial instinct was to rewrite from a class component to a function component, however upon further inspection I realised it had 1100 lines of code, with relatively complicated lifecycle methods.

I decided to wrap the component with a functional HoC that called the hook, and passed the result down to the component as a prop. In normal JavaScript, it isn't _too_ complicated, you'd do something like this:

```tsx
import React, { useState } from 'react';

export function withExtraInfo(WrappedComponent) {
  const [extraInfo, setExtraInfo] = useState('');
  const ComponentWithExtraInfo = props => {
    return <WrappedComponent {...props} extraInfo={extraInfo} />;
  };
  return ComponentWithExtraInfo;
}
```

However for TypeScript, typing a HoC can become a little bit confusing, especially if you read some of the blog posts out there. If you tried to run TypeScript against the code above, you'd need to fix a few things:

1. Both `WrappedComponent` and `props` have an implicit `any` type
2. Make the function generic

Here's how we'd do that:

```ts
import React, { useState } from 'react';

// First we need to add a type to let us extend the incoming component.
type ExtraInfoType = {
  extraInfo: string;
};
// Mark the function as a generic using P (or whatever variable you want)
export function withExtraInfo<P>(
  // Then we need to type the incoming component.
  // This creates a union type of whatever the component
  // already accepts AND our extraInfo prop
  WrappedComponent: React.ComponentType<P & ExtraInfoType>
) {
  const [extraInfo, setExtraInfo] = useState('');
  setExtraInfo('important data.');

  const ComponentWithExtraInfo = (props: P) => {
    // At this point, the props being passed in are the original props the component expects.
    return <WrappedComponent {...props} extraInfo={extraInfo} />;
  };
  return ComponentWithExtraInfo;
}
```

You'll probably notice we marked `withExtraInfo` as a generic using `<P>`. For more information, see the <a href="https://www.typescriptlang.org/docs/handbook/generics.html#working-with-generic-type-variables">TypeScript Handbook</a>.

To wrap things up, you'll want to [add a displayName](https://reactjs.org/docs/higher-order-components.html#convention-wrap-the-display-name-for-easy-debugging) to your HoC, which I've left as an exercise for the reader.


<a href="https://twitter.com/share?url=https%3A%2F%2Fdev.to%2Frozenmd%2Fhow-to-implement-a-higher-order-component-in-react-with-typescript-3n21&amp;text=How to implement a Higher-order component in React with TypeScript&amp;via=RozenMD" target="_blank" rel="noopener noreferrer">If this post helped you, I'd <b>really</b> appreciate a share on Twitter.</a>