组件类型定义
很多人可能在使用 TypeScript 编写 React 应用的时候会对三种不同的函数返回值类型产生困惑,不明白它们之间的区别以及应该什么时候使用哪一种类型才比较严谨。
ReactElement
是含有 props 和 type 属性的对象:
type Key = string | number
interface ReactElement<P = any, T extends string | JSXElementConstructor<any> = string | JSXElementConstructor<any>> {
type: T;
props: P;
key: Key | null;
}
ReactNode
则是多种类型的集合:
type ReactText = string | number;
type ReactChild = ReactElement | ReactText;
interface ReactNodeArray extends Array<ReactNode> {}
type ReactFragment = {} | ReactNodeArray;
type ReactNode = ReactChild | ReactFragment | ReactPortal | boolean | null | undefined;
类组件的 render 成员函数会返回 ReactNode 类型的值,而且 PropsWithChildren 类型中指定的 children 类型也是 ReactNode。
const Comp: FunctionComponent = props => <div>{props.children}</div>
// children?: React.ReactNode
type PropsWithChildren<P> = P & {
children?: ReactNode;
}
虽然 React 的类型定义看起来写得很复杂,但它实际上等价于:
type ReactNode = {} | null | undefined;
由于 {}
是所有对象的原型,你可以把几乎任何类型赋值给 ReactNode,但绝大多数情况下应该对它进行更详细的类型声明。
JSX.Element
通过执行 React.createElement 或是转译 JSX 获得。
const jsx = <div>hello</div>
const ele = React.createElement("div", null, "hello");
<p> // <- ReactElement = JSX.Element
<Custom> // <- ReactElement = JSX.Element
{true && "test"} // <- ReactNode
</Custom>
</p>
JSX 是一个全局的命名空间,不同的库对 JSX 都可以有自己不同的实现,而 React 的实现方式就是让 JSX.Element 等价于 ReactElement,同时将它的泛型 props 和 type 都设为 any:
declare global {
namespace JSX {
interface Element extends React.ReactElement<any, any> { }
}
}
返回类型的不同
有的同学可能会注意到:类组件渲染方法的返回值类型和函数组件的是不一样的,这是因为目前版本的 TypeScript 类型定义并不能准确地限定 React 实际值的范围:
- 类组件类型定义:通过 render() 返回 ReactNode,比 React 的实际值范围更宽松
- 函数组件类型定义:返回 JSX.Element,也比 React 的实际值范围更宽松
实际上 React 类组件中的 render() 和函数组件的返回类型是一样的,而 TypeScript 只是出于历史原因和向后兼容需要,为不同种类的组件声明了不同的返回值类型。
根据 文档的规定 我们可以为组件返回值给出准确的类型定义:
type ComponentReturnType = ReactElement | Array<ComponentReturnType> | string | number | boolean | null
// 注意: 不能传入 undefined
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!