Поиск машинописного текста из литерала объекта - PullRequest
0 голосов
/ 12 марта 2020

У меня есть такой литерал объекта в Typescript:

const data={
  a:'valueOfA',
  b:'valueOfB,
  ...
}

Затем мне нужно обновить значения в разных местах, передав объект и свойство для обновления следующим образом:

function update(obj,prop){
...
}
update(data,'a');

Это, конечно, работает, но я бы хотел получить доступ к свойству с помощью точечной нотации и воспользоваться преимуществами intellisense в IDE. Таким образом, я могу вызвать функцию следующим образом:

update(data,KeysOfData.a);

Я сделал первую реализацию, которая хорошо работает и предоставляет intellisense, но мне это кажется довольно уродливым, и я хотел бы знать, есть ли лучшие способы получить результат. Вот текущая реализация:

type FormProps = {
    firstName?: string,
    lastName?: string,
    email?: string
}

const formData: FormProps = {
    firstName: '',
    lastName: '',
    email: ''
}

type FormItemName = keyof FormProps;
type FormItem = {
    [key in FormItemName]: string
}

// Generates lookup object
const Fields: FormItem = Object.keys(formData).reduce<FormItem>((obj, field) => {
    obj[field as FormItemName] = field;
    return obj;
}, {} as any);


// Later call to update
update(formData,Fields.firstName);

1 Ответ

0 голосов
/ 18 марта 2020

Во-первых, я хотел бы отметить, что «Как я могу сделать этот код чище / лучше» считаются плохими вопросами переполнения стека, см. Как спросить для получения дополнительной информации о 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!);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...