在使用 react 和 TypeScript 开发项目时,很多人都会遇到类型报错的问题。满屏的“类型不匹配”红线不仅打断思路,也让人感到困扰。如果你也曾为ReactNode、JSX.Element 和 ReactElement 这几个类型的选择而纠结,这篇文章或许能帮你理清思路。
先说结论:组件的 props,尤其是 children,建议使用 React.ReactNode;而组件的返回值类型,则应使用 JSX.Element。React.ReactElement 通常只用于一些更复杂或底层的场景。
先看两个例子:
const node: JSX.Element = <p />; // ✅ 正确,只能接受 JSX
const node2: React.ReactNode = "Hello" || 42 || <p />; // ✅ 正确,可接受多种类型
JSX.Element 是一个比较严格的类型,通常用于描述组件的返回内容。
React.ReactNode 则宽松很多,可以表示任何可以被 React 渲染的内容,包括字符串、数字、布尔值、null、undefined 或 JSX 元素。
因此,在声明组件的 props,特别是 children 时,使用 ReactNode 是更合适的选择:
interface Props {
children: React.ReactNode; // ✅ 推荐写法
}
const Component: React.FC<Props> = ({ children }) => <p>{children}</p>;
如果你错误地将 children 定义为 JSX.Element,那么像 <Component>Hello</Component> 这样的写法就会报错,因为字符串不被视为 JSX.Element。
简单总结:props 尤其是内容型 prop 用 ReactNode,组件返回值用 JSX.Element。
TypeScript 最初并不支持 JSX语法,后来通过 .tsx 文件和 tsconfig 中的 jsx 选项才实现兼容,并逐渐形成了当前这一套类型系统。
JSX.Element:用于约束返回类型
很多人习惯将 children 定义为 JSX.Element,这其实限制过大。因为 React 不仅可以渲染 JSX,还能渲染字符串、数字、null 等原始类型。
JSX.Element 实际上是一个扩展自 ReactElement 的接口,大致结构如下:
declare global {
namespace JSX {
interface Element extends React.ReactElement<any, any> {}
}
}
因此,它最适合用于组件的返回类型,例如:
const MyComponent = (): JSX.Element => <p>Hello</p>;
但不适用于需要灵活内容的 props。
React.ReactNode:更灵活的内容类型
ReactNode 的设计初衷就是涵盖所有可渲染的内容,其类型定义包括:
type ReactNode =
| ReactElement
| string
| number
| boolean
| null
| undefined
| ReactNodeArray;
因此它特别适合用于接收动态内容,比如 children、标题、页脚等:
interface CardProps {
title: React.ReactNode;
extra?: React.ReactNode;
children: React.ReactNode;
}
这样定义之后,无论是传递文字、数字还是 JSX,TypeScript 都不会报错。
React.ReactElement:底层元素对象
ReactElement 类型描述的是 JSX 编译后的元素对象结构,包含 type 和 props 等属性。它通常在工具函数或高阶组件中使用,用于直接操作元素结构。
例如:
function mapChildren(children: React.ReactElement[]): React.ReactElement[] {
return children.map(child => {/* 处理逻辑 */});
}
在日常业务组件中,一般不需要直接使用这个类型。
类型 | 适用场景 | 例子 |
---|---|---|
React.ReactNode | children 或其他内容型 props | <p>{123}</p>, <Title text="Hello" /> |
JSX.Element | 函数组件的返回值 | const Comp = (): JSX.Element => <p />; |
React.ReactElement | 操作元素结构或工具函数 | cloneElement(element, newProps) |
children 基本上总是应该写成 React.ReactNode。
组件的返回类型推荐明确标注为 JSX.Element,有助于代码检查和团队协作。
除非你明确要处理元素对象,否则不要使用 React.ReactElement。
如果在编写过程中遇到类型错误,可以先问自己:我是在传递内容,还是在声明返回类型?如果是传递内容,选 ReactNode;如果是返回类型,就用 JSX.Element。
只要记住一个原则:props 用 ReactNode,返回值用 JSX.Element,就能避免大部分类型错误。ReactElement 仅用于少数高级场景。合理运用这些类型,不仅能减少报错,还能让代码更清晰、更易于维护。
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!
在JavaScript中存在这样两种原始类型:Null与Undefined。这两种类型常常会使JavaScript的开发人员产生疑惑,在什么时候是Null,什么时候又是Undefined?Undefined类型只有一个值,即undefined。当声明的变量还未被初始化时,变量的默认值为undefined。
主要介绍了JS中检测数据类型的几种方式,typeof运算符用于判断对象的类型,但是对于一些创建的对象,它们都会返回\'object\',有时我们需要判断该实例是否为某个对象的实例,那么这个时候需要用到instanceof运算符
对于object和number、string、boolean之间的转换关系,ToPrimitive是指转换为js内部的原始值,如果是非原始值则转为原始值,调用valueOf()和toString()来实现。
Undefined类型表示未定义,它的类型只有一个值为undefined。undefined和null有一定的表意差别。非整数的Number类型无法使用 == 或 === 来比较,因为 JS 是弱类型语言,所以类型转换发生非常频繁
近在做项目代码重构,其中有一个要求是为代码添加智能提示和类型检查。智能提示,英文为 IntelliSense,能为开发者提供代码智能补全、悬浮提示、跳转定义等功能,帮助其正确并且快速完成编码。
基本类型:按值访问,可以操作保存在变量中实际的值;引用类型数据存在堆内存,而引用存在栈区,也就是说引用类型同时保存在栈区和堆区,关于==的执行机制,ECMASript有规范,因为==前后的值交换顺序,返回的值也是一样的,所以在此对规范做出如下总结
JavaScript 是一种弱类型或者说动态类型语言。所以你不用提前声明变量的类型,在程序运行时,类型会被自动确定,你也可以使用同一个变量保存不同类型的数据。
js的值传递和引用(地址)传递:js的5种基本数据类型 number,string,null,undefined,boolean 在赋值传递时是值传递,js的引用数据类型(object,array,function)进行引用传递,其实底层都是对象。
JS中所有的值都可以转换成布尔类型 使用Boolean()或者 !!(两个感叹号),JS中所有的值都可以转换成数字类型,使用Number()或+。数字类型转换场景目的只有一个,用于计算,将后台传递的数据,从字符串转换为数字并参与计算
众所周知,JS在很多情况下会进行强制类型转换,其中,最常见两种是:1.使用非严格相等进行比较,对==左边的值进行类型转换2.在if判断时,括号内的值进行类型转换,转化为布尔值
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!