Children type in React and TypeScript: a complete guide

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

What lies behind the children prop in React and TypeScript?

\n\n

If you've ever written a React component using TypeScript, you've likely encountered the question: "What data type is the children prop?". This question is one of the most popular on Stack Overflow, and for good reason. At first glance, the answer seems simple: ReactNode. But as they say, the devil is in the details.

\n\n

In this article, we won't just give a dry answer. We'll break down all possible types for children, their differences, best practices, and pitfalls. You'll learn when to use ReactNode, when to use ReactElement, and when to use more specific types. Let's go!

\n\n

Why is this question so popular?

\n\n

The problem is that children is a special prop in React. It can be anything:

\n\n
    \n
  • A string: "Hello, world!"
  • \n
  • A number: {42}
  • \n
  • A JSX element: <div>...</div>
  • \n
  • An array of elements: [<span/>, <span/>]
  • \n
  • A function (render prop): {() => <div/>}
  • \n
  • Even null, undefined, or boolean
  • \n
\n\n

Because of this flexibility, beginners often write children: any, which negates all the benefits of TypeScript. Let's figure out the correct approaches.

\n\n

Main types for children

\n\n

1. ReactNode — the universal soldier

\n\n

This is the most common and correct type for children in 90% of cases. It includes everything that React can render.

\n\n
import { ReactNode } from 'react';\n\ninterface CardProps {\n  title: string;\n  children: ReactNode;\n}\n\nfunction Card({ title, children }: CardProps) {\n  return (\n    <div className="card">\n      <h2>{title}</h2>\n      <div className="card-content">\n        {children}\n      </div>\n    </div>\n  );\n}\n\n// Usage:\n<Card title="My Card">\n  <p>This text will be rendered</p>\n  {123} {/* Numbers also work */}\n  {null} {/* And null */}\n</Card>
\n\n

What is included in ReactNode? It is essentially a union of:

\n
    \n
  • ReactElement — JSX elements
  • \n
  • string and number — primitives
  • \n
  • boolean, null, undefined — ignored during rendering
  • \n
  • ReactNode[] — an array of the above
  • \n
  • ReactPortal — portals
  • \n
\n\n

2. ReactElement — strict mode

\n\n

If you need children to be only a JSX element (not a string or number), use ReactElement.

\n\n
import { ReactElement } from 'react';\n\ninterface StrictCardProps {\n  children: ReactElement; // Only one JSX element\n}\n\nfunction StrictCard({ children }: StrictCardProps) {\n  return <div className="strict-card">{children}</div>;\n}\n\n// Works:\n<StrictCard><span>Only an element</span></StrictCard>\n\n// TypeScript error:\n<StrictCard>Text</StrictCard> // ❌ String is not allowed
\n\n

Important: ReactElement requires exactly one child element. If you pass two elements without a wrapper, TypeScript will also throw an error.

\n\n

3. JSX.Element — an alias for ReactElement

\n\n

The type JSX.Element is simply ReactElement<any, any>. It is less flexible than ReactNode and is generally not recommended for children unless you are writing a library.

\n\n
// Essentially, these are the same:\ntype A = JSX.Element;    // ReactElement<any, any>\ntype B = ReactElement;   // Re                

Blogs

Book Recommendations