You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React TypeScript封装Semantic-UI组件遇类型错误求助

解决TypeScript封装Semantic-UI-React组件的类型错误

错误原因

你的泛型T没有添加类型约束,TypeScript无法推断传入的Element组件props类型必然包含children和className,因此抛出类型不兼容的错误;同时Wrapper函数的返回类型定义错误,应该返回接受T类型props的组件,而非接受ComponentType<T>的组件。

修正方案

  1. 给泛型T添加约束,确保它继承包含children、可选className及其他任意属性的类型
  2. 调整Wrapper的返回类型为React.NamedExoticComponent<T>,匹配memo化组件的类型
  3. 让组件接收的参数类型直接对应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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 13:01:41