ReactJS TypeScript中如何为动态组件传递联合类型的动态Props?
我有一个Next.js首页,通过getServerSideProps接收数组格式的homeData作为props,同时定义了组件映射对象pages,根据Redux中的currentStep(0-6的数字)渲染对应组件,并传递homeData[currentStep]作为组件的data属性。
各组件都有自己的Props类型定义,比如Welcome组件的Props:
type WelcomeProps = { data: { title: string subtitle: string sim_image: string packages: string[] } handleStepClick: (direction: 'next' | 'prev') => void }
当前问题是:在VS Code中hover查看data props时,它的类型显示为各组件Props中data类型的交集,但我期望它是联合类型(即WelcomeProps['data'] | SimTypeProps['data'] | ...)。
核心问题是TypeScript无法自动关联currentStep、pages中的组件以及homeData的索引对应关系,导致类型推断错误。可以通过以下步骤修复:
1. 定义步骤与Data类型的映射
先为每个步骤对应的data类型创建一个映射类型,明确步骤编号和对应数据结构的关系:
// 先导入或定义各组件的Props类型 import type { WelcomeProps } from './Welcome'; import type { SimTypeProps } from './SimType'; import type { NumberSearchProps } from './NumberSearch'; // ... 其他组件的Props类型 // 建立步骤编号与对应data类型的映射 type StepDataMap = { 0: WelcomeProps['data']; 1: SimTypeProps['data']; 2: NumberSearchProps['data']; 3: ShoppingCartProps['data']; 4: PersonalInformationProps['data']; 5: ShippingAddressProps['data']; 6: OrderConfirmationProps['data']; };
2. 为homeData指定正确类型
将首页接收的homeData类型从any改为StepDataMap(数组索引与步骤编号对应,符合TypeScript的索引类型推断):
export default function Home({ homeData }: { homeData: StepDataMap }) { // ... 后续代码 }
3. 约束组件映射对象的类型
给pages对象指定类型,让它的键对应步骤编号,值是接收对应data类型的组件,确保组件与数据类型的匹配:
const pages: { [K in keyof StepDataMap]: React.ComponentType<{ data: StepDataMap[K]; handleStepClick?: (direction: 'next' | 'prev') => void; }> } = { 0: Welcome, 1: SimType, 2: NumberSearch, 3: ShoppingCart, 4: PersonalInformation, 5: ShippingAddress, 6: OrderConfirmation, };
4. 约束currentStep的类型
确保currentStep的类型是keyof StepDataMap(即0|1|2|3|4|5|6),而不是宽泛的number。如果Redux的selectStep返回的是number,可以通过类型断言缩小范围:
const currentStep = useSelector(selectStep) as keyof StepDataMap;
最终效果
完成上述修改后,当hover查看data={homeData[currentStep]}时,TypeScript会正确推断出它的类型是StepDataMap[keyof StepDataMap],也就是所有步骤对应data类型的联合类型,而非交集。
内容的提问来源于stack exchange,提问作者Robin

