Tipo children en React y TypeScript: guía completa

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

¿Qué se esconde detrás del prop children en React y TypeScript?

\n\n

Si alguna vez has escrito un componente en React usando TypeScript, seguramente te has enfrentado a la pregunta: "¿Qué tipo de datos tiene el prop children?". Esta pregunta es una de las más populares en Stack Overflow, y no es para menos. A primera vista, parece que la respuesta es simple: ReactNode. Pero, como se dice, el diablo está en los detalles.

\n\n

En este artículo no solo daremos una respuesta seca. Analizaremos todos los tipos posibles para children, sus diferencias, mejores prácticas y trampas. Aprenderás cuándo usar ReactNode, cuándo ReactElement y cuándo tipos más específicos. ¡Allá vamos!

\n\n

¿Por qué esta pregunta es tan popular?

\n\n

El problema es que children es un prop especial en React. Puede ser cualquier cosa:

\n\n
    \n
  • Una cadena: "¡Hola, mundo!"
  • \n
  • Un número: {42}
  • \n
  • Un elemento JSX: <div>...</div>
  • \n
  • Un array de elementos: [<span/>, <span/>]
  • \n
  • Una función (render prop): {() => <div/>}
  • \n
  • Incluso null, undefined o boolean
  • \n
\n\n

Debido a tanta flexibilidad, los principiantes suelen escribir children: any, lo que anula todo el beneficio de TypeScript. Analicemos los enfoques correctos.

\n\n

Tipos principales para children

\n\n

1. ReactNode — el todoterreno

\n\n

Este es el tipo más común y correcto para children en el 90% de los casos. Incluye todo lo que React puede renderizar.

\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// Uso:\n<Card title="Mi tarjeta">\n  <p>Este texto será renderizado</p>\n  {123} {/* Los números también funcionan */}\n  {null} {/* Y null */}\n</Card>
\n\n

¿Qué incluye ReactNode? Básicamente es la unión de:

\n
    \n
  • ReactElement — elementos JSX
  • \n
  • string y number — primitivos
  • \n
  • boolean, null, undefined — se ignoran al renderizar
  • \n
  • ReactNode[] — array de lo anterior
  • \n
  • ReactPortal — portales
  • \n
\n\n

2. ReactElement — modo estricto

\n\n

Si necesitas que children sea solo un elemento JSX (no una cadena ni un número), usa ReactElement.

\n\n
import { ReactElement } from 'react';\n\ninterface StrictCardProps {\n  children: ReactElement; // Solo un elemento JSX\n}\n\nfunction StrictCard({ children }: StrictCardProps) {\n  return <div className="strict-card">{children}</div>;\n}\n\n// Funciona:\n<StrictCard><span>Solo elemento</span></StrictCard>\n\n// Error de TypeScript:\n<StrictCard>Texto</StrictCard> // ❌ La cadena no es válida
\n\n

Importante: ReactElement requiere exactamente un elemento hijo. Si pasas dos elementos sin envolverlos, TypeScript también dará error.

\n\n

3. JSX.Element — alias de ReactElement

\n\n

El tipo JSX.Element es simplemente ReactElement<any, any>. Es menos flexible que ReactNode y generalmente no se recomienda para children, a menos que estés escribiendo una biblioteca.

\n\n
// Básicamente, es lo mismo:\ntype A = JSX.Element;    // ReactElement<any, any>\ntype B = ReactElement;   // Re                

Blogs

Book Recommendations