React TypeScript封装Semantic-UI组件遇类型错误求助
解决TypeScript封装Semantic-UI-React组件的类型错误
错误原因
你的泛型T没有添加类型约束,TypeScript无法推断传入的Element组件props类型必然包含children和className,因此抛出类型不兼容的错误;同时Wrapper函数的返回类型定义错误,应该返回接受T类型props的组件,而非接受ComponentType<T>的组件。
修正方案
- 给泛型
T添加约束,确保它继承包含children、可选className及其他任意属性的类型 - 调整Wrapper的返回类型为
React.NamedExoticComponent<T>,匹配memo化组件的类型 - 让组件接收的参数类型直接对应
T,保证与Element的props完全对齐
修正后的代码
Wrapper.tsx
import { ComponentType, PropsWithChildren, memo, NamedExoticComponent } from 'react'; import classNames from 'classnames'; function Wrapper<T extends PropsWithChildren<{ className?: string } & Record<string, any>>>( Element: ComponentType<T>, styles: string, ): NamedExoticComponent<T> { const memoizedComponent = ({ children, className, ...props }: T) => ( <Element {...props} className={classNames(styles, className)} > {children} </Element> ); return memo(memoizedComponent); } export default Wrapper;
Grid.ts(无需修改)
import { Grid as SemanticGrid, GridProps } from 'semantic-ui-react' import Wrapper from 'ui/Wrapper' import styles from './styles.module.scss' const Grid = Wrapper<GridProps>(SemanticGrid, styles.grid)
关于memo与子元素的说明
memo默认会浅比较props,若children是动态生成的引用类型(比如每次渲染创建新组件/对象),会导致memo失效。此时可以给memo传递第二个参数自定义比较逻辑,示例如下:
return memo(memoizedComponent, (prevProps, nextProps) => { // 自定义比较规则,比如忽略children变化,仅比较指定props return Object.is(prevProps.className, nextProps.className) && Object.is(prevProps.stackable, nextProps.stackable) && Object.is(prevProps.columns, nextProps.columns); });
内容的提问来源于stack exchange,提问作者Cracs
相关产品推荐
相关产品推荐

