Typing React Props in TypeScript
Tags: react, typescript, webdev, beginners
Published: 2021-07-07 14:31:44

---
title: Typing React Props in TypeScript
published: true
description: 
tags: react, typescript, webdev, beginners
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/84yo496d79bm8vho79jb.png
---
 
One advantage of using React with TypeScript is that you can easily type the props of your (function) components. You don't have to use React's [PropTypes](ttps://reactjs.org/docs/typechecking-with-proptypes.html) because TypeScript already has its own typing system.

In the following, I will show you how to define custom props for a component in connection with already existing props like `children`.
<!--more-->
## Starting Example

**PostPreview.tsx**

```tsx
import React from 'react';

export interface Props {
  heading: string;
}

const PostPreview = (props: Props) => {
  return (
    <div>
      <h1>{props.heading}</h1>
      {props.children}
    </div>
  );
};

export default PostPreview;
```

As you can see, our `PostPreview` component has a `heading` property. The component is supposed to render the `heading` and other components (`children`) below the heading. In technical terms this is called [Containment](https://reactjs.org/docs/composition-vs-inheritance.html#containment).

Because our `Props` interface only defines the heading, the following error shows up:

> TS2339: Property 'children' does not exist on type 'Props'.

Let me show you three different ways to solve this problem.

## Solution 1: `PropsWithChildren`

The easiest way to solve the problem is to use the generic type `PropsWithChildren`. It supports a [generic type variable](https://www.typescriptlang.org/docs/handbook/2/generics.html#working-with-generic-type-variables), so that we can use our `Props` with it:

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

export interface Props {
  heading: string;
}

const PostPreview = (props: PropsWithChildren<Props>) => {
  return (
    <div>
      <h1>{props.heading}</h1>
      {props.children}
    </div>
  );
};

export default PostPreview;
```

The solution is simple, but it doesn't describe our component very well. The compiler knows that our component can have children, but it doesn't know whether our component has other tag-specific properties. We also have to remind ourselves to import React. So let's take a look at a more advanced solution.

## Solution 2: `React.FC`

`React.FC` specifies a [function component](https://reactjs.org/docs/components-and-props.html#function-and-class-components) and lets us also assign a type variable. It uses `PropsWithChildren` behind the scenes, so we don't have to worry about connecting our `Props` with it:

```tsx
import React from 'react';

export interface Props {
  heading: string;
}

const PostPreview: React.FC<Props> = (props) => {
  return (
    <div>
      <h1>{props.heading}</h1>
      {props.children}
    </div>
  );
};

export default PostPreview;
```

Thanks to the use of `React.FC`, the TypeScript compiler now knows that our `PostPreview` constant is a React component. We no longer have to think about importing React ourselves, as the compiler already prompts us to do so. However, the compiler still does not know how our component looks like in detail. It cannot tell whether it is a `<div>` element or a `<p>` element or something else. Hence we come to solution number three.

## Solution 3: `React.HTMLProps`

The most specialized version is to extend `React.HTMLProps`. The `HTMLProps` support a variety of tags (`HTMLDivElement`, `HTMLFormElement`, `HTMLInputElement`, etc.). Make sure that the type variable matches the outmost tag (the first tag, that is mentioned after `return`):

```tsx
import React from 'react';

export interface Props extends React.HTMLProps<HTMLDivElement> {
  heading: string;
}

const PostPreview: React.FC<Props> = (props: Props) => {
  return (
    <div>
      <h1>{props.heading}</h1>
      {props.children}
    </div>
  );
};

export default PostPreview;
```

With this variant our component inherits all properties of a `<div>` element and extends them with custom props like `heading`. 

Our `PostPreview` component can now be used as follows:

**IndexPage.tsx**

```tsx
import React from 'react';
import PostPreview from './PostPreview';

const IndexPage: React.FC = () => {
  return (
    <div>
      <PostPreview heading="First Post">
        <p>#1</p>
      </PostPreview>

      <PostPreview heading="Second Post">
        <p>#2</p>
      </PostPreview>
    </div>
  );
};

export default IndexPage;
```

Tested with: React v17.0.2

## Get connected 🔗

Please [follow me on Twitter](https://twitter.com/bennycode) or [subscribe to my YouTube channel](https://www.youtube.com/c/typescripttv) if you liked this post. I would love to hear from you what you are building. 🙂 Best, Benny