JSX.Element vs React.ReactNode
最近看antd源码关于render元素有这样两个类型定义 JSX.Element,React.ReactNode,心生疑惑,两者有何差异呢,这里Mark下。
先说大结论【俗称废话】,两者不一样
JSX.Element与React.ReactNode等价?
创建一个Card组件,参数content定义为JSX.Element,如果传参为数组元素,是直接报错的。改为JSX.Element[]
或者React.ReactNode
均OK。
那是不是意味着这样就等价了呢?
JSX.Element[]与React.ReactNode等价?
No,ReactNode的类型定义如下
1 | type ReactNode = ReactChild | ReactFragment | ReactPortal | string | number | boolean | null | undefined; |
也就说可以接受各种类型,而Element一定要是个React Element[当然可以是原生Element]
1 | interface ReactElement<P> { |
比如上面例子,如果类型定义为JSX.Element,content要是个数字就会报类型错误。
技术性解释
摘自大神的回答
Quote @ferdaber: A more technical explanation is that a valid React node is not the same thing as what is returned by React.createElement. Regardless of what a component ends up rendering, React.createElement always returns an object, which is the JSX.Element interface, but React.ReactNode is the set of all possible return values of a component.
- JSX.Element -> Return value of React.createElement
- React.ReactNode -> Return value of a component
antd里的类型定义
明白了差异,再重新看antd里关于这个类型的使用,似乎也就更理解了。
比如对于常用的Table组件,render方法与renderColumnTitle采用了不同的类型定义。why?因为两者确实情况不同
render 使用JSX.Element
因为table组件最终一定返回一个组件元素,不可能是个数字,字符串等
renderColumnTitle使用React.ReactNode
如上renderColumnTitle返回的可能只是个数字,字符串等,并不是个元素对象
写在最后
正确合理使用类型定义,可以避免一些BUG,同时也提升代码可读性。TS的大量使用使我觉得类型这块着实充当了一部分文档的作用。