我想为具有以下属性的表列定义接口:
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”确保安全?
答案 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
}
]
};
希望有帮助。祝你好运!