React组件渲染遇TypeScript类型冲突:交集类型被缩减为never
React组件联合类型传参的类型冲突解决
问题原因
你当前的代码里,TypeScript没办法通过findIndex的结果,将传入的mode和对应的组件props类型建立关联。它会把找到的Component的props推断成MovieInfoModeProps | PlaylistInfoModeProps,而data是movieModeDataType | playlistModeDataType,两者交叉后因为image等属性的类型冲突,直接缩减为never,所以触发了类型错误。
解决方案
方案一:给模式数组添加精确类型映射
通过定义模式与组件props的映射关系,让TypeScript能明确每个模式对应的组件和数据类型:
首先修改类型定义文件:
export type movieModeDataType = { image: string, name: string, quality: string, rate: string, genre: string[], } export type playlistModeDataType = { name: string, image?: never, quality?: never, rate?: never, genre?: never } // 定义每个模式对应的组件props类型 type ModeComponentPropsMap = { movie: { data: movieModeDataType }, playlist: { data: playlistModeDataType } } // 基于映射生成组件的props类型 export type infoPresenterProps = { [K in keyof ModeComponentPropsMap]: { mode: K, ...ModeComponentPropsMap[K] } }[keyof ModeComponentPropsMap]
然后修改组件文件:
import React from "react"; import { infoPresenterProps, ModeComponentPropsMap } from "types/components/info-presenter/infoPresenter.type"; import MovieInfoMode from "components/info-presenter/modes/movie/MovieInfoMode"; import PlaylistInfoMode from "components/info-presenter/modes/playlist/PlaylistInfoMode"; // 定义模式项的类型 type ModeEntry<K extends keyof ModeComponentPropsMap> = { key: K, Component: React.ComponentType<ModeComponentPropsMap[K]> } const MODES: ModeEntry<keyof ModeComponentPropsMap>[] = [ { key: "movie", Component: MovieInfoMode }, { key: "playlist", Component: PlaylistInfoMode } ] export default function InfoPresenter({ mode, data }: infoPresenterProps) { const modeEntry = MODES.find(item => item.key === mode) as ModeEntry<typeof mode>; return <modeEntry.Component data={data} />; }
方案二:用条件判断替代数组查找(更直观)
如果模式数量不多,直接用switch或if判断,TypeScript会自动在每个分支里推断出正确的data类型:
import { infoPresenterProps } from "types/components/info-presenter/infoPresenter.type"; import MovieInfoMode from "components/info-presenter/modes/movie/MovieInfoMode"; import PlaylistInfoMode from "components/info-presenter/modes/playlist/PlaylistInfoMode"; export default function InfoPresenter({ mode, data }: infoPresenterProps) { switch(mode) { case "movie": return <MovieInfoMode data={data} />; case "playlist": return <PlaylistInfoMode data={data} />; default: throw new Error(`不支持的模式:${mode}`); } }
内容的提问来源于stack exchange,提问作者Amirreza Pourkairm
相关产品推荐
相关产品推荐

