JSX.Element, ReactNode, ReactElement:在 TypeScript 中何时使用它们?

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

JSX.Element vs ReactNode vs ReactElement:你必须赢得的类型之战



你好,同行!如果你在用 React 和 TypeScript 编写代码,那么你一定遇到过编译器对返回值类型报错的情况。“Expected JSX.Element, got ReactNode”——这个错误熟悉吗?或者,你可能在泛型中见过 ReactElement,并思考过:“它们到底有什么区别?”



剧透:这不仅仅是学术术语。正确选择类型可以加速你的代码,防止错误,并使组件更可预测。今天,我们将通过实际示例来深入探讨这个主题,让你再也不会混淆这三种类型。开始吧!



快速入门:它们分别是什么



让我们从基础开始。这三种类型都属于同一个生态系统,但抽象程度不同。



ReactElement

这是基本的构建块。ReactElement 是一个包含类型、props 和 key 的对象。它代表了 React 随后将转换为真实 DOM 节点的“蓝图”。如果你编写 React.createElement('div', null, 'Hello'),你得到的就是 ReactElement。



import React from 'react';

const element: React.ReactElement = React.createElement('div', { className: 'box' }, '你好!');// 类型:ReactElement<{ className: string }, 'div'>


重要提示: ReactElement 是一个泛型。你可以指定 props 的类型和元素的类型:



type MyElement = React.ReactElement<{ name: string }, 'button'>;


JSX.Element

这是ReactElement 的扩展,增加了 JSX 的特性。本质上,JSX.Element 就是 ReactElement<any, any>。当你在 JSX 中编写 <div /> 时,TypeScript 会将其视为 JSX.Element。



const jsxElement: JSX.Element = <div>JSX.Element</div>;


与 ReactElement 的主要区别在于 JSX.Element 不是参数化的。它只是“任何 JSX 元素”。



ReactNode

这是最宽泛的类型。ReactNode 包括:

  • ReactElement
  • 字符串
  • 数字
  • 布尔值 (true/false)
  • null 和 undefined
  • 上述类型的数组
  • React Portal


简单来说:ReactNode 是 React 可以渲染的所有内容。这个类型正是用于组件中的 children。



type ReactNode =   | React.ReactElement  | string  | number  | boolean  | null  | undefined  | React.ReactNode[];


何时使用什么?实际场景



现在是最有趣的部分——让我们分析一下在实际情况下应该选择哪种类型。



场景 1:组件的返回值

你的组件返回 JSX。应该指定什么类型?



// ❌ 不好:类型过于宽泛function MyComponent(): ReactNode {  return <div>你好</div>;}

// ✅ 好:使用 JSX.Elementfunction MyComponent(): JSX.Element { return <div>你好</div>;}

// ✅ 优秀:如果需要严格的 props 类型化function MyComponent(): React.ReactElement<{ title: string }> { return <div>你好</div>;}


为什么? 组件总是返回 JSX(或者 null,如果不渲染任何内容)。ReactNode 过于宽泛——它允许返回字符串、数字或数组,这可能导致意外的错误。



场景 2:组件中的 children

在这里,ReactNode 是你最好的朋友。子元素可以是任何内容:字符串、另一个组件、null(条件渲染)或数组。



interface CardProps {  title: string;  children: React.ReactNode; // ✅ 正确}

function Card({ title, children }: CardProps): J

博客

书籍推荐