如何正确编写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,提问作者Роман Василаки
相关产品推荐
相关产品推荐

