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

如何正确编写React动态组件?解决TypeScript类型不兼容报错

React动态组件TypeScript "never"类型报错解决方案

在编写React动态组件时,会遇到TypeScript报错:Type * is not assignable to type 'never'. The intersection * was reduced to 'never' because property * has conflicting types in some constituents。以下是报错场景的示例代码,且各实体类型差异较大,无法使用公共类型方案:

type OneType = {
  title: string;
  component: 'One';
};
const One = ({ title }: OneType) => {
  return <div>{title}</div>;
};

type TwoType = {
  price: number;
  component: 'Two';
};
const Two = ({ price }: TwoType) => {
  return <div>{price}</div>;
};

type ThreeType = {
  name: string;
  component: 'Three';
};
const Three = ({ name }: ThreeType) => {
  return <div>{name}</div>;
};

const components = {
  One,
  Two,
  Three,
};

type EntityType = OneType | TwoType | ThreeType;

const entities: EntityType[] = [
  { title: 'some', component: 'One' },
  { price: 9999, component: 'Two' },
  { name: 'some', component: 'Three' },
];

function App() {
  return (
    <>
      {entities.map((entity) => {
        const Component = components[entity.component];
        return <Component {...entity} />;
      })}
    </>
  );
}

export default App;

报错原因

TypeScript无法自动关联entity的具体类型与对应组件的props类型。当展开{...entity}时,它会尝试计算所有EntityType成员的类型交集,但OneType/TwoType/ThreeType的props字段(title/price/name)互相冲突,导致交集被缩减为never,进而触发报错。

解决方案

方案1:类型断言(快速解决)

通过类型断言跳过TypeScript的类型检查,适用于确定实体与组件对应关系绝对正确的场景:

function App() {
  return (
    <>
      {entities.map((entity) => {
        const Component = components[entity.component];
        return <Component {...entity as never} />;
      })}
    </>
  );
}

方案2:类型安全的组件映射(推荐)

通过明确组件与props的对应关系,让TypeScript正确推导类型,避免类型冲突:

// 定义组件与对应props的映射类型
type ComponentPropsMap = {
  One: OneType;
  Two: TwoType;
  Three: ThreeType;
};

// 约束components对象的类型
const components: {
  [K in keyof ComponentPropsMap]: (props: ComponentPropsMap[K]) => JSX.Element;
} = {
  One,
  Two,
  Three,
};

type EntityType = ComponentPropsMap[keyof ComponentPropsMap];

const entities: EntityType[] = [
  { title: 'some', component: 'One' },
  { price: 9999, component: 'Two' },
  { name: 'some', component: 'Three' },
];

function App() {
  return (
    <>
      {entities.map((entity) => {
        const Component = components[entity.component];
        return <Component {...entity} />;
      })}
    </>
  );
}

方案3:泛型渲染函数

通过泛型函数强化类型关联,进一步提升类型安全性:

type EntityType = OneType | TwoType | ThreeType;

const components = {
  One,
  Two,
  Three,
};

// 泛型函数确保entity与组件props类型匹配
function renderEntity<T extends EntityType>(entity: T) {
  const Component = components[entity.component] as (props: T) => JSX.Element;
  return <Component {...entity} />;
}

function App() {
  return (
    <>
      {entities.map(renderEntity)}
    </>
  );
}

内容的提问来源于stack exchange,提问作者Роман Василаки

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 20:50:22