Во-первых, я хотел бы отметить, что «Как я могу сделать этот код чище / лучше» считаются плохими вопросами переполнения стека, см. Как спросить для получения дополнительной информации о topi c.
Однако, учитывая, что вы новый участник, я буду рассматривать этот вопрос как вопрос о том, как использовать непатентованные значения и keyof
, чтобы сделать ваш код многократно используемым и повысить безопасность типов. Заранее прошу прощения, если вы не подходите под эту категорию, и просите лучшего ответа. В этом случае просто отредактируйте ваш вопрос, чтобы быть более точным в отношении того, чего вы хотите достичь sh.
Первое предложение: ваше решение, но с использованием обобщений
Вы можете извлечь ваша реализация, чтобы вы могли использовать ее для других объектов, например так:
// Generic reusable lookup type
type FieldLookup<T> = { [key in keyof T]: string }
// Generic reusable lookup generation function
function generateFieldLookup<T>(data: T): FieldLookup<T> {
return Object.keys(formData).reduce((obj, field) => {
obj[field as keyof T] = field;
return obj;
}, {} as FieldLookup<T>)
}
// Generates lookup object
const Fields = generateFieldLookup(formData)
// Later call to update
update(formData, Fields.firstName);
Однако этот тип говорит о том, что свойство T также является свойством объекта поиска, в качестве значения которого используется некоторая строка, более правильный тип был бы:
type FieldLookup<T> = { [key in keyof T]: key; }
function generateFieldLookup<T>(data: T): FieldLookup<T> {
return Object.keys(formData).reduce((obj, field) => {
const key = field as keyof T;
obj[key] = key;
return obj;
}, {} as FieldLookup<T>)
}
Теперь, когда вы наводите курсор мыши на Fields.firstName
, вы также получите его точное значение типа. Тем не менее, он скажет, что undefined
это возможность. Это потому, что нигде в типе не говорится, что все поля включены в поиск.
Если это вызывает проблемы для вас где-то в коде, просто сделайте Fields.firstName!
Второе предложение: Введите update
Если вы можете пожертвовать способностью чтобы в среде IDE вы могли получать предложения, когда вы нажимаете точку, и просто хотите, чтобы безопасность типов и предложения были наведены на функцию, чтобы получить выводимый тип, вы можете покончить со всей этой реализацией и просто ввести обновление как:
function update<T>(obj: T, prop: keyof T): void
// Later call to update
update(formData, 'firstName');
Обратите внимание, что это предложение исключает предыдущее, вы можете использовать оба.
Если вы это сделаете, вам придется использовать более продвинутую версию реализации в первое предложение, с восклицательным знаком, т.е. сделать:
// Generic reusable lookup type
type FieldLookup<T> = { [key in keyof T]: key }
function update<T>(obj: T, prop: keyof T): void
// Later call to update
update(formData, Fields.firstName!);