React.memo组件类型差异:MemoExoticComponent与NamedExoticComponent区别
解答
1. 类型差异与报错的原因
SimpleMemo正常的原因:Simple组件的_props没有显式声明类型,TypeScript会默认推断为any。React.memo包装这个组件后,会保留props的any类型——any类型允许任意属性传递,所以style不会触发类型检查错误,对应的类型就是MemoExoticComponent<(_props: any) => JSX.Element>。SimpleMemo2报错的原因:匿名组件的_props没有显式声明类型,但你给函数返回值标注了JSX.Element,TypeScript会默认把_props推断为object类型。但TypeScript中的object是一个宽泛的类型,仅表示“非原始类型”,不包含任何具体属性定义。所以当你传递style属性时,TypeScript会检测到该属性不在object的属性集中,从而抛出错误。同时因为是匿名函数,React.memo返回的类型就变成了NamedExoticComponent<object>。
2. MemoExoticComponent与NamedExoticComponent的区别
MemoExoticComponent:是React.memo包装有名称的组件(比如Simple这种具名函数组件)后返回的类型,它会完整保留原组件的props类型信息,本质是一个专门用于记忆化渲染的组件包装器。NamedExoticComponent:当直接给React.memo传递匿名函数组件时,TypeScript会将其推断为这个类型。它的props类型默认会被推断为object(如果没有显式声明),相比MemoExoticComponent,它丢失了原组件更精确的props类型约束。
3. 让匿名函数版React.memo正常使用的方法
核心是给匿名组件的props显式声明正确的类型,有几种方式:
方式一:声明HTML元素属性类型
如果组件要接收style这类原生HTML元素的属性,可以直接用React.HTMLAttributes:
const SimpleMemo2 = React.memo((_props: React.HTMLAttributes<HTMLDivElement>): JSX.Element => { return <div>Hello</div>; });
方式二:允许任意属性(快速解决,不推荐用于严格场景)
如果不需要严格的类型检查,可以直接把props声明为any:
const SimpleMemo2 = React.memo((_props: any): JSX.Element => { return <div>Hello</div>; });
方式三:使用泛型指定props类型
先定义props类型,再通过泛型传递给React.memo:
type MyComponentProps = React.HTMLAttributes<HTMLDivElement>; const SimpleMemo2 = React.memo<MyComponentProps>((_props) => { return <div>Hello</div>; });
这样TypeScript就能正确识别props的合法属性,style等属性就能正常传递了。
内容的提问来源于stack exchange,提问作者Timmmm
相关产品推荐
相关产品推荐

