繁体   English   中英

Typescript 和 React:如何从父组件动态推断类型?

[英]Typescript and React: How to dynamically infer types from the parent component?

我有一个通用组件,用于沿代码构建特定表。 我们称之为GenericTable 它的工作流程如下所示:

表格渲染工作流程

为了简化问题,假设GenericTable只有两个道具: columnsrows

export const Page1 = () => {
return (
    <GenericTable
      columns={page1Columns}
      rows={page1Rows}
    />
  );
};

export const Page2 = () => {
    return (
        <GenericTable
          columns={page2Columns}
          rows={page2Rows}
        />
      );
    };

假设columnsrows的类型可能因页面而异。 例如, Page1可能有一个只显示数字的表格,而Page2可能有一个更复杂的表格,其中包含字符串、数字甚至其他组件。 这样, GenericTablepropertiestypes应该如下所示:

type GenericTableProps<ColumnType, RowType> {
    columns: ColumnType;
    rows: RowType;
  }
    
  export const GenericTable = <
    ColumnType extends Page1ColumnType | Page2ColumnType,
    RowType extends Page1RowType | Page2RowType
  >(
    props: GenericProps<ColumnType, RowType>
  ) => {
    // build the table here using the columns and rows props
  }

这里的问题是,由于我可能有不止两个页面调用GenericTable ,我不想硬编码Page1ColumnTypePage1RowType等类型。 如何从传递它的页面动态推断列和行类型?

例如,如果Page3GenericTable中调用,它如何推断ColumnType扩展Page3ColumnType而无需对其进行硬编码。

考虑这个例子:

type Page1ColumnType = {
    tag: 'Page1ColumnType'
}
type Page2ColumnType = {
    tag: 'Page2ColumnType'
}

type Page1RowType = {
    tag: 'Page1RowType'
}

type Page2RowType = {
    tag: 'Page2RowType'
}

type GenericTableProps<ColumnType, RowType> = {
    columns: ColumnType;
    rows: RowType;
}

export const GenericTable = <
    ColumnType extends Page1ColumnType | Page2ColumnType,
    RowType extends Page1RowType | Page2RowType
>(
    props: GenericTableProps<ColumnType, RowType>
) => { }

GenericTable的类型签名是不安全的,因为ColumnTypeRowType彼此不相关/不绑定。 这意味着从 typescript 的角度来看,这个调用是完全有效的:

const result = GenericTable({
    columns: {
        tag: 'Page1ColumnType'
    },
    rows: {
        tag: 'Page2RowType'
    }
})

您是否注意到列是Page1和行是Page2 为了绑定列和行,您需要将其作为一个数据结构的一部分:


type GenericTableProps<ColumnType, RowType> = {
    columns: ColumnType;
    rows: RowType;
}

type DataStructure =
    | GenericTableProps<Page1ColumnType, Page1RowType>
    | GenericTableProps<Page2ColumnType, Page2RowType>

export const GenericTable = (
    props: DataStructure
) => { }

// ERROR
GenericTable({
    columns: {
        tag: 'Page1ColumnType'
    },
    rows: {
        tag: 'Page2RowType' // wrong value
    }
})

// OK
GenericTable({
    columns: {
        tag: 'Page1ColumnType'
    },
    rows: {
        tag: 'Page1RowType' // ok
    }
})

操场

如果您不想预先对所有允许的状态进行硬编码,您仍然需要了解 map 的类型。 如果你会给我提供预期的行和列接口,我会尝试编写通用 function,因为我不知道行和列的形状以及它们之间的关系

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM