Tipo children em React e TypeScript: guia completo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

O que está por trás da prop children em React e TypeScript?

\n\n

Se você já escreveu um componente React usando TypeScript, certamente já se deparou com a pergunta: "Qual é o tipo de dado da prop children?". Esta pergunta é uma das mais populares no Stack Overflow, e não é à toa. À primeira vista, parece que a resposta é simples: ReactNode. Mas o diabo, como dizem, está nos detalhes.

\n\n

Neste artigo, não vamos apenas dar uma resposta seca. Vamos analisar todos os tipos possíveis para children, suas diferenças, melhores práticas e armadilhas. Você aprenderá quando usar ReactNode, quando usar ReactElement e quando usar tipos mais específicos. Vamos lá!

\n\n

Por que esta pergunta é tão popular?

\n\n

O problema é que children é uma prop especial no React. Ela pode ser qualquer coisa:

\n\n
    \n
  • String: "Olá, mundo!"
  • \n
  • Número: {42}
  • \n
  • Elemento JSX: <div>...</div>
  • \n
  • Array de elementos: [<span/>, <span/>]
  • \n
  • Função (render prop): {() => <div/>}
  • \n
  • Até mesmo null, undefined ou boolean
  • \n
\n\n

Devido a essa flexibilidade, iniciantes frequentemente escrevem children: any, o que anula todos os benefícios do TypeScript. Vamos entender as abordagens corretas.

\n\n

Tipos principais para children

\n\n

1. ReactNode — o coringa universal

\n\n

Este é o tipo mais comum e correto para children em 90% dos casos. Ele inclui tudo que o React pode 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="Meu cartão">\n  <p>Este texto será renderizado</p>\n  {123} {/* Números também funcionam */}\n  {null} {/* E null */}\n</Card>
\n\n

O que está incluído em ReactNode? Na prática, é a união de:

\n
    \n
  • ReactElement — elementos JSX
  • \n
  • string e number — primitivos
  • \n
  • boolean, null, undefined — ignorados na renderização
  • \n
  • ReactNode[] — array dos itens acima
  • \n
  • ReactPortal — portais
  • \n
\n\n

2. ReactElement — modo estrito

\n\n

Se você precisa que children seja apenas um elemento JSX (não string ou número), use ReactElement.

\n\n
import { ReactElement } from 'react';\n\ninterface StrictCardProps {\n  children: ReactElement; // Apenas um elemento JSX\n}\n\nfunction StrictCard({ children }: StrictCardProps) {\n  return <div className="strict-card">{children}</div>;\n}\n\n// Funciona:\n<StrictCard><span>Apenas elemento</span></StrictCard>\n\n// Erro do TypeScript:\n<StrictCard>Texto</StrictCard> // ❌ String não é aceita
\n\n

Importante: ReactElement exige exatamente um elemento filho. Se você passar dois elementos sem um wrapper, o TypeScript também emitirá um erro.

\n\n

3. JSX.Element — alias para ReactElement

\n\n

O tipo JSX.Element é simplesmente ReactElement<any, any>. Ele é menos flexível que ReactNode e geralmente não é recomendado para children, a menos que você esteja escrevendo uma biblioteca.

\n\n
// Na prática, é a mesma coisa:\ntype A = JSX.Element;    // ReactElement<any, any>\ntype B = ReactElement;   // Re                

Blogs

Book Recommendations