打字稿:推断对象内函数参数的查找类型

时间:2018-08-15 10:51:04

标签: typescript types

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

export class MybindCustomAttribute {
      static inject = [Element];

      constructor(element){
        this.element = element;
      }

      valueChanged(newValue, oldValue){
        this.element.innerHTML += newValue;
      }
}

组件类具有以下签名:

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

和道具:

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

因此可以正确推断该类的具体类型。

为完整起见,在PagedTable内,单元格的简化呈现功能为:

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
}

我想要的是让renderCell(datum: T, { customRender, key }: ColumnDef<T>) { if (customRender) { return customRender(datum[key!], datum, key!) } else { return datum[key] } } 在使用customRender函数时获得正确的类型。在此设置中,其类型为targetData,这是错误的。

有没有一种方法可以仅使用架构对象的number | string属性(保证是数据对象的键)来推断类型?

2 个答案:

答案 0 :(得分:1)

我认为您的主要问题是您可能不希望customRender成为通用函数。并非任何customRender都可以将T[U]用作任何 U,而每个customRender都希望有特定的< / em> U。毕竟,(targetData, row) => fnThatOnlyTakesStrings(targetData)似乎期望targetData是一个string,它仅适用于某些 specific 键,对吧?

所以我认为您确实希望ColumnDefTU中都是通用的,就像这样:

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所做的更改是否必要,或者是否表现出预期的效果,但是我遇到了与参数数量有关的错误,并且我对其进行了修正,直到没有抱怨为止。您应该对其进行更改以适合您的需求。


希望有帮助。祝好运。

答案 1 :(得分:1)

如果我正确理解这一点,那么棘手的方面是schema可以有多个ColumnDef不同类型的密钥,以及每个 {{1} }需要与其ColumnDef函数相对应。为了让TypeScript为每个customRender推断和实施不同的类型,您需要将每个ColumnDef包装在函数调用中。然后我发现我需要显式指定ColumnDef以便进行推理。希望这不会造成麻烦,因为我认为在实际的应用程序中您已经具有T的类型定义。这段代码对我有用:

T