Это хитроумно.
Имея
interface Column {
field: string
label: string
}
Мы можем определить RowObject
и, кроме того, просто для примера, Row
, который имеет column
свойство и сам row
.
interface RowObject {
[key: string]: string;
}
interface Row {
cols: Column[];
object: RowObject;
}
Теперь мы должны определить функцию для создания прототипа новых объектов.
const createRowBlueprint = (cols: Column[]): Row => {
return {
cols: [...cols],
object: cols.map(c => c.field)
.reduce((prop: RowObject, prev: string) => (prop[prev] = '', prop), {})
};
};
Я только что определил интерфейс Row
для динамического доступа свойства "реального объекта строки", например,
const row = createRowBlueprint(cols);
row.cols.forEach(col => {
const { field } = col;
const value = row.object[field];
console.log(`Field ${field} binded to ${value}`);
});
Учитывая вашу коллекцию columns
, это выдает следующее
{
cols: [
{ label: 'First Name', field: 'fname' },
{ label: 'Last Name', field: 'lname' },
{ label: 'Email', field: 'email' }
],
row: { fname: '', lname: '', email: '' }
}
Field fname binded to
Field lname binded to
Field email binded to
Очевидно, я устанавливаю значение по умолчанию для пустой строки , Но доказательство того, что это работает, состоит в том, что значение, доступное из поля, не undefined
.
Наконец, этот подход не является безопасным типом. Но, насколько мне известно, Typescript на данный момент не поддерживает определение типа динамического c во время компиляции ... Так что это сложный обходной путь.
Надеюсь, это поможет.