Что такое операторы Pick, Partial, Omit, Required, NonNullable и Exclude в TypeScript
Что проверяют
Умеете ли вы выводить типы из существующих, а не копировать интерфейсы вручную, и понимаете ли, как эти утилиты устроены внутри. Следом часто просят написать Pick или Partial самостоятельно или объяснить разницу между Omit и Exclude.
Как отвечать
Сначала уточните формулировку: это не операторы, а встроенные утилитные типы, собранные из mapped и conditional types. Их удобно делить на две группы.
Работают со свойствами объекта:
Partial<T>: все свойства становятся необязательными. Типичный случай: тело PATCH-запроса или обновление части состояния формы;Required<T>: снимает?со всех свойств модификатором-?;Pick<T, K>: оставляет выбранные ключи,Kобязан входить вkeyof T, опечатку компилятор поймает;Omit<T, K>: убирает ключи. В React так строят пропсы обёртки:Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'type'>.
Работают с объединениями:
Exclude<T, U>: выбрасывает из юниона члены, совместимые сU. Это дистрибутивный условный типT extends U ? never : T;NonNullable<T>: убираетnullиundefined, с TypeScript 4.8 определён какT & {}.
Реализацию показать полезно, она короткая:
type MyPick<T, K extends keyof T> = { [P in K]: T[P] };
type MyPartial<T> = { [P in keyof T]?: T[P] };Хорошо назвать соседей: Extract как обратный к Exclude, Readonly, Record, ReturnType, Parameters, Awaited.
Где спотыкаются
Путают Omit и Exclude. Omit убирает свойства из объектного типа, Exclude убирает варианты из юниона, поэтому Exclude<User, 'email'> вернёт User без изменений.
Не знают, что Omit не проверяет ключи: у него K extends keyof any, и Omit<User, 'emial'> пройдёт молча. Строгую версию пишут сами или берут из type-fest.
Ждут глубокой работы. Partial и Required действуют только на верхний уровень, вложенные объекты остаются как были. А Omit на юнионе не дистрибутивен: Omit<A | B, 'id'> оставит только общие ключи, поля отдельных вариантов пропадут, и сужение по дискриминанту сломается.