泛型的自动类型解析

时间:2019-06-26 13:31:19

标签: typescript

我想为具有以下属性的表列定义接口:

  • title:列标题
  • key:特定模型中属性的键(这样我就可以得到值)
  • valueFormatter:用于格式化返回字符串的值的任何函数

valueFormatter-Function应该获取一个参数,该参数的类型与属性(键)相同。像这样。

export interface Column<T, P extends keyof T> {
  label: string;
  key: P;
  valueFormatter?: (value: T[P]) => string
};

是否可以在其他接口中使用此方法而无需显式定义“ P”类型,如下所示:

export interface Table<T> {
  data: T[];
  columns: Column<T>[];
}

或者:如何在没有P-Generic的情况下定义列接口,并通过“ key”和“ valueFormatter”确保安全?

1 个答案:

答案 0 :(得分:3)

我个人倾向于将columns设为每个T键具有一个属性的对象,因为您大概不想冒丢失其中一列的风险:

interface Column<T, P extends keyof T> {
  label: string;
  key: P;
  valueFormatter?: (value: T[P]) => string;
}

interface TableWithColumnObject<T> {
  data: T[];
  columnObject: { [K in keyof T]: Column<T, K> };
}

columnObject是一个mapped type,您可以这样使用它:

interface Person {
  name: string;
  age: number;
}

const table1: TableWithColumnObject<Person> = {
  data: [{ name: "Alice", age: 35 }, { name: "Bob", age: 38 }],
  columnObject: {
    name: {
      label: "Name",
      key: "name",
      valueFormatter: name => name
    },
    age: {
      label: "Age",
      key: "age",
      valueFormatter: age => "" + age
    }
  }
};

如果您不希望丢失其中一列(或者您可能想要丢失某些列或包括重复项),则可以通过使用columnObject映射类型以稍微复杂一些的方式:

interface TableWithColumnArray<T> {
  data: T[];
  columnArray: { [K in keyof T]: Column<T, K> }[keyof T][];
}

在这里,我们采用映射类型及其looked up的属性,并说我们想要一个数组。因此,对于Person,该类型类似于Array<Column<Person, "name"> | Column<Person, "age">>。我们这样使用它:

const table2: TableWithColumnArray<Person> = {
  data: [{ name: "Alice", age: 35 }, { name: "Bob", age: 38 }],
  columnArray: [
    {
      label: "Name",
      key: "name",
      valueFormatter: name => name
    },
    {
      label: "Age",
      key: "age",
      valueFormatter: age => "" + age
    }
  ]
};

希望有帮助。祝你好运!

Link to code