I was making some Table components using Next.js, typescript, and type-graphql.
There are various custom object types of data, but eventually, they should be rendered into table rows.

Even though the detailed shape of the row would be different because the shapes of each data are different,
They are the same in that they should be rendered into a list of rows.

所以我想根据列表数据的类型来制作泛型列表组件,以减少重复代码的编写.

I'll roughly explain the code with the types of data as animals.
Currently inside of CatList.tsx:

const CatList = () => {
  const { list, total } = useQuery(/* data fetching */)
  // list is type of Cat[]
  
  return (
    <BaseTable>
      {/* this block is what I wanted to make into generic components */}
      {list.map((item: Cat) => (
        <CatListRow data={item} /*...other props*/ />
      )}
    </BaseTable>
  )
}

// same with dog in different file

const DogList = () => {
  const { list, total } = useQuery(/* data fetching */)
  // list is type of Dog[]
  
  return (
    <BaseTable>
      {list.map((item: Dog) => (
        <DogListRow data={item} /*...other props*/ />
      )}
    </BaseTable>
  )
}

我想把每一张单子列成这样:

const CatList = () => {
  const { list, total } = useQuery(/* data fetching */)
  
  return (
    <BaseTable>
      <Rows list={list} /* ...other props */ />
    </BaseTable>
  )
}

我试着像这样赚Rows.tsx美元:

type TableTarget = Cat | Dog | ... ;
/** each type has common fields
* __typename (string - ex: "Cat")
* id
* createdAt
* ...etc
*/

interface RowProps<T> {
  data: T;
}

const CatRow = ({ data }: RowProps<Cat>) => {
  /* Cat Row */
}

const DogRow = ({ data }: RowProps<Dog>) => {
  /* Dog Row */
}


const getRowComponentByType = (target: TableTarget) => {
  switch(target.__typename) {
    case 'Cat':
      return CatRow;
    case 'Dog':
      return DogRow;
    ...
  }
}


interface RowsProps<T extends TableTarget> {
  list: T[];
}

const Rows = <T>({ list }: RowsProps<T>) => {
  if (list.length === 0) {
    return (
      <tr>list is empty.</tr>
    )
  }
  
  const Row = getRowComponentByType(list[0])
  return (
    <>
      {list.map((item: T) => {
        <Row data={item} />
        {/* red underline on 'data' prop */}
        {/* error message: 'TableTarget' is not assignable to 'Cat & Dog' */}
      })}
    </>
  )
}

export default Rows;

我想知道如何在正确使用打字脚本泛型的情况下完成Rows组件.

提前谢谢您.

推荐答案

这对我很管用,但如果你需要进一步的帮助,我想我需要一次闪电战

type Cat = {};
type Dog = {};
type TableTarget = Cat | Dog;

interface RowsProps<T extends TableTarget> {
  list: T[];
}

function Rows<T extends TableTarget>({ list }: RowsProps<T>): any {
  list.map(() => {

  })
}

function row<T extends TableTarget>(props: RowsProps<T>): any{
  return {list: []}
}

Typescript相关问答推荐

如何将单元测试中的私有订阅变量设置为空(或未定义)?

Typescript如何从字符串中提取多个文本

属性的类型,该属性是类的键,其值是所需类型

单击并移除for循环中的一项也会影响另一项

使用Dockerfile运行Vite React应用程序时访问env变量

接口重载方法顺序重要吗?

如果数组使用Reaction-Hook-Form更改,则重新呈现表单

TypeScrip泛型类未提供预期的类型错误

我怎样才能正确地输入这个函数,使它在没有提供正确的参数时出错

自动通用回调

如何从对象或类动态生成类型

是否可以通过映射类型将函数参数约束为预定义类型?

有没有办法传递泛型类型数组,以便推断每个元素的泛型类型?

扩展对象的此内容(&Q;)

可赋值给类型的类型,从不赋值

替换typescript错误;X类型的表达式可以';t用于索引类型Y;带有未定义

Select 类型的子项

在ts中获取级联子K类型?

传入类型参数<;T>;变容函数

Typescript 编译错误:TS2339:类型string上不存在属性props