代码之家  ›  专栏  ›  技术社区  ›  n00dle

具有联合类型和泛型的Typescript数组要求编译时字段是可选的

  •  0
  • n00dle  · 技术社区  · 4 年前

    我试图在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新手,所以我怀疑我误解了应该如何推断属性类型。很乐意接受关于构建此架构的最佳方法的建议。

    0 回复  |  直到 4 年前