#typescript
Вопрос:
Чего я пытаюсь достичь, так это создать служебную функцию, которая исключает экземпляр и объект и обновляет экземпляр с помощью предоставленных значений полей ввода. Вот функция полезности:
function updateEntity<T, K extends keyof T>(
entity: T,
updateInput: { [key in K]: T[K] },
): void {
return Object.keys(updateInput).forEach((key) => {
entity[key as K] = updateInput[key as K];
});
}
и вот у меня есть экземпляр и интерфейс обновления:
class Animal {
name: string = 'no name';
isMale: boolean = false;
}
type Input = Partial<{
name: string;
}>;
const input: Input = {
name: 'str'
};
const cat = new Animal();
updateEntity(cat, input); // input is an error
Я получаю следующую ошибку:
Argument of type 'Partial<{ name: string; }>' is not assignable to parameter of type '{ name: string; }'.
Types of property 'name' are incompatible.
Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'.(2345)
Я не думаю, что полностью понимаю сообщение об ошибке. Мое намерение состояло в том, чтобы частично обновить исходный экземпляр с помощью предоставленных входных данных.
Входные данные должны быть подмножеством исходного экземпляра (без дополнительных полей).
Вот ссылка на игровую площадку: ссылка
Что я упускаю?
Комментарии:
1. Не связано, но ваша частичная часть кажется немного излишней,
name?: string
вы просто сделали бы то же самое, вы имели в видуtype Input = Partial<Animal>
, или если бы вам нужно было только имяtype Input = Partial<Pick<Animal, 'name'>>
, иначе вы могли бы определить имя как строку в одном месте и логическое значение в другом, кажется гораздо более чистым, чтобы тип имени определялся только один раз.2. Это всего лишь простой пример, хотя я мог бы сделать
Partial<Animal>
то, что я хочу, чтобы у меня был выделенный интерфейс/тип
Ответ №1:
Используйте ненулевое утверждение. Когда вы наведете курсор на updateInput
параметр, его тип будет { [key in K]?: T[K] | undefined }
таким, потому что поля, которые отсутствуют, будут такими undefined
. TypeScript по-прежнему считает, что updateInput[key]
это может быть undefined
скорее, чем T[K]
, но мы почти уверены, что updateInput[key]
это может быть только тип T[K]
.
function updateEntity<T, K extends keyof T>(
entity: T,
updateInput: { [key in K]?: T[K] },
): void {
for (const key in updateInput) {
entity[key] = updateInput[key]!;
}
}
Комментарии:
1. Это позволит полям за пределами T. См. cide здесь: typescriptlang.org/play? #код/…