How to define the React children type in Typescript?

About

This article will show you how to override/define the type of children of your react component to a specific type in your props.

Step by Step Example

The component to refactor

In this example, we have a layout component that expects only buttons as children to create a button bar.

The base component is as follows where the props accepted are for div element (ie React.HTMLAttributes<HTMLDivElement>)

export function ButtonGroup(props: React.HTMLAttributes<HTMLDivElement>) {

    return (
        <div className={'btn-group flex-wrap'} {...props}/>
    )
}

Step 1: Changing the default children type

The props.children attributes by default have the type React.ReactNode or undefined

To override it to only buttons, you would:

  • use the Omit function to exclude the children attribute
  • add your children's type definition

Example:

export function ButtonGroup(
   props: Omit<React.HTMLAttributes<HTMLDivElement>,"children"> 
      & { 
          children: HTMLButtonElement[] 
          // with your button component
          // children: (ReactElement<typeof YourButtonComponent>|HTMLButtonElement)[]
      }) {
  ...
} 

Step2: Fixing the typescript error

Once you have changed your signature with your type definition, you will get the following typescript error:

TS2322: Type HTMLButtonElement is not assignable to type ReactNode
Type HTMLButtonElement is missing the following properties from type ReactPortal: props, key
index.d.ts(2318, 9): The expected type comes from property children which is declared here on type
DetailedHTMLProps<HTMLAttributes<HTMLDivElement>, HTMLDivElement>

React Typescript Children Override Error

Why? Because the div element in React is a React Node and excepts as children a ReactNode or undefined

It does not like your new definition.

To resolve this problem, you need to override the type by defining it back to a ReactNode (ie children as unknown as React.ReactNode)

Example:

export function ButtonGroup({children, ...props}: 
    Omit<React.HTMLAttributes<HTMLDivElement>, "children"> &
    {
        children: HTMLButtonElement[]
    }
) {

    return (
        <div className={'btn-group flex-wrap'} {...props}>
            {children as unknown as React.ReactNode}
        </div>
    )
}

Conclusion

And here you are, you got your typescript component that accepts your type in our case: only buttons.

Note that it adds some complexity and even if you have created a type children component, you may not want to deal with further typescript problem such as

  • type. An anchor may also be styled as a button
  • performance. Typescript needs to parse and apply narrower restrictions.

And leave the restriction to the developer.





Discover More
React - Component (User-defined Element)

A component is a user-defined react element in the React tree. Components let you split the UI into independent, reusable pieces, and think each piece in isolation. Conceptually, components are like...
React Props Chrome Plugin
React - Props

props is the only object argument passed from a component to another component. Props are similar to State, but is public and not fully controlled by the component. You can also pass arguments to...



Share this page:
Follow us:
Task Runner