Механизм Partial<T> был введен в TypeScript, чтобы облегчить работу с объектами, свойства которых могут быть временно не определены. Исторически разработчикам приходилось создавать новые типы вручную, где все свойства делались опциональными, что приводило к дублированию кода и ошибкам.
Изначально для обновления или создания объектов с необязательными полями приходилось явно указывать каждое опциональное свойство, что было неудобно и не поддерживало изменения исходного интерфейса. Так появился utility type Partial<T>, который автоматически превращает все свойства типа T в опциональные.
При проектировании API часто требуется обновлять только часть объекта, не затрагивая остальные поля. Это особенно актуально для PATCH-запросов, форм обновления и функций, обрабатывающих только часть данных. Без Partial типизация становится сложной и хрупкой.
Используется utility type Partial<T>, который определен примерно так:
// Упрощённо: type Partial<T> = { [P in keyof T]?: T[P] };
Таким образом, все свойства делают опциональными. Пример:
interface User { id: number; name: string; email: string; } function updateUser(id: number, user: Partial<User>) { // ... } // Можно передать только изменяемое updateUser(1, { email: "test@example.com" });
Ключевые особенности:
Можно ли с помощью Partial сделать обязательные все поля исходного интерфейса?
Нет, Partial делает все свойства опциональными. Для обратной задачи есть тип Required<T>.
Что произойдет, если использовать Partial с уже опциональными свойствами?
Partial просто не изменит уже опциональных свойств, все поля останутся опциональными, даже если были такими до применения Partial.
Пример:
interface X { x?: number; y: string; } const a: Partial<X> = {}; // оба свойства теперь опциональны
Можно ли использовать Partial для вложенных структур, если требуется сделать опциональными только вложенные поля?
Partial не распространяется рекурсивно на вложенные объекты. Если нужно сделать все вложенные свойства опциональными — придётся писать свой Generic-тип либо использовать сторонние утилиты.
В CRUD-системе updateUser принимает Partial<User> и позволяет передавать пустой объект, что приводит к ошибкам на рантайме: обязательные поля стираются.
Плюсы:
Минусы:
Partial<User> применяется только для описания input-формы обновления. На финальном этапе все поля валидируются и мержатся с оригинальным объектом до передачи в базу.
Плюсы:
Минусы: