首页 > 解决方案 > 打字稿:推断对象内函数参数的查找类型

问题描述

定义通用表。这需要数据和如何显示它的模式。这是如何调用它的简化示例。

<PagedTable
  data={[ username: 'rob', logins: 32 ]}
  schema={[
    {
      key: 'username',
      customRender: (targetData, row) => fnThatOnlyTakesStrings(targetData)
    } 
   ]}
 />

组件类具有以下签名:

class PagedTable<T> extends Component<Props<T>, any>

和道具:

interface Props<T> {
  data: T[] | null | undefined
  schema: ColumnDef<T>[]
}

interface ColumnDef<T> {
  key?: keyof T
  customRender?: <U extends keyof T>(
    targetData: T[U],
    rowData: T
  ) => string | JSX.Element
}

所以类的具体类型被正确推断。

为了完整起见,在 PagedTable 中,单元格的简化渲染函数是:

renderCell(datum: T, { customRender, key }: ColumnDef<T>) {
  if (customRender) {
    return customRender(datum[key!], datum, key!)
  } else {
    return datum[key]
  }
}

我想要的是targetData在使用 customRender 函数时获得正确的类型。在此设置中,它的类型number | string不正确。

key有没有办法仅使用模式对象的属性(保证是数据对象的键)来推断类型?

标签: typescripttypes

解决方案


我认为您的主要问题是您可能不想customRender成为通用函数。不应该是 any可以接受customRendera ,而是每个人都期望一个特定的。毕竟,似乎期望那是 a ,它只适用于某些特定的键,对吧?T[U] UcustomRender U(targetData, row) => fnThatOnlyTakesStrings(targetData)targetDatastring

所以我认为你真的想ColumnDef在两者中都通用TU就像这样:

interface ColumnDef<T, U extends keyof T> {
  key?: U
  customRender?: (
    targetData: T[U],
    rowData: T
  ) => string | JSX.Element
}

这最终需要传播到引用的其他事物ColumnDef

interface Props<T, U extends keyof T> {
  data: T[] | null | undefined
  schema: ColumnDef<T, U>[]
}

class PagedTable<T, U extends keyof T> extends React.Component<Props<T, U>, any> {
  renderCell(datum: T, cd: ColumnDef<T, U>) {
    if (cd.customRender) {
      return cd.customRender(datum[cd.key! as any as U], datum)
    } else {
      return datum[cd.key!]
    }
  }
}

(我不确定我所做的更改renderCell是否必要,或者它的行为是否符合预期,但我遇到了与参数数量有关的错误,我修复了它,直到它没有抱怨。你应该改变它以适应你的需要)。


希望有帮助。祝你好运。


推荐阅读