Один из подходов состоит в том, чтобы полагаться на сопоставленные типы TypeScript .
. Это будет "отображать" все ключи (Key in keyof
) в переданном родовом (Row
).
Затем для каждой клавиши Row
(например, name
, age
, admin
) мы назначим объект формы, который вы обрисовали, со свойствами header
, field
и format
.
Однако, поскольку теперь мы знаем, что работаем с конкретным ключом (например, age
), мы можем использовать Key
для ссылки на age
в этом отображенном наборе и Row[Key]
для ссылки на типиз age
(number
).
Наконец, вам не нужны ключи с вложенными объектами, вам нужны только объекты, поэтому мы можем эффективно «собрать» эти значения с помощью [keyof Row]
, просматривая всезначения для "age" | "name" | "admin"
и оставленный тип объединения всех возможных столбцов с правильно набранными field
и format
.
type Columns<Row> = {
[Key in keyof Row]: {
header: string;
field: Key,
format?: (value: Row[Key]) => string;
}
}[keyof Row]
const rows = [{name: 'Alice', age: 18, admin: true }, {name: 'Bob', age: 12, admin: false}];
type Row = typeof rows[0];
const columns: Columns<Row>[] = [
{
header: 'Name',
field: 'name',
format: value => value.toUpperCase(), // value: string
},
{
header: 'Age',
field: 'age',
format: value => value.toLocaleString(), // value: number
},
{
header: 'Admin',
field: 'admin',
format: value => value.toString(), // value: boolean
},
];
TypeScript Playground