我试图在TypeScript下为我的React路由器配置创建一个页面映射。由于每个页面将由不同的组件类型生成,并且这些不同的组件将具有不同的属性,因此我希望使用通用容器,但保留组件与其props接口之间的语义链接。
我希望地图的每个元素都由几个字段定义,名义上是名称、显示页面的组件以及该组件的相关道具。我认为仿制药似乎是一种明智的方法:
type PageDef<T> = {
name: string;
component: FunctionComponent<T>;
props: T;
}
注意:我也尝试将其作为一个接口,但也有同样的问题。
)
对于本例,假设我已经定义了两个props接口和两个相应的功能组件(实际上还有很多…):
export interface PropsOne {
test_1: string
}
export interface PropsTwo {
test_2: number
}
function ComponentOne(props: PropsOne) {
return <div> {props.test_1} </div>
}
function ComponentTwo(props: PropsTwo) {
return <div> {props.test_2} </div>
}
然后,我创建一个页面映射,如下所示:
type SupportedPages = PageDef<PropsOne> | PageDef<PropsTwo>;
const pages: Array<SupportedPages> = [
{
name: "Page one",
component: ComponentOne,
props: {
test_1: "Hello, world"
}
},
{
name: "Page two",
component: ComponentTwo,
props: {
test_2: 42
}
}
]
到目前为止没有错误!
当我开始使用时,问题就来了
pages
在我的主页组件中:
function MainPage(props: { pages: Array<SupportedPages> }) {
return <div>
{props.pages.map(page => {
const PageComponent = page.component;
return <PageComponent {...page.props}/>
})}
</div>
}
在这里,我有一个错误
PageComponent
TS2322: Type '{ test_1: string; } | { test_2: string; }' is not assignable to type 'IntrinsicAttributes & PropsOne & { children?: ReactNode; } & PropsTwo'.
Property 'test_2' is missing in type '{ test_1: string; }' but required in type 'PropsTwo'.
我真的不明白这告诉我什么-似乎道具类型被推断为两个道具的交点?不过我很确定我希望是工会。
如果页面的类型为
FunctionalComponent<PropsOne>
那么
props
应该是
PropsOne
,它不应该关心
PropsTwo
,反之亦然。
我是TS新手,所以我怀疑我误解了应该如何推断属性类型。很乐意接受关于构建此架构的最佳方法的建议。