Видеоуроки, интерактивный редактор и сохранение прогресса — бесплатно, сразу после входа.
ВойтиСоздать аккаунт — бесплатноЗакончили урок?
Войдите, чтобы отмечать прогресс
Pick<User, "name"> разворачивается в { name: string }. Поле email в этом типе не объявлено, поэтому строка ниже становится ошибкой лишнего свойства, и директива @ts-expect-error наконец делает свою работу.
Второй аргумент Pick это не строка в кавычках «просто так», а литеральный тип ключа. Несколько ключей перечисляются через union:
И компилятор проверяет, что такие ключи вообще существуют:
Именно поэтому опечатка в имени поля здесь ловится сразу, в отличие от ручного переписывания типа.
keyof User даёт union всех ключей ("name" | "email" | "age"), ограничение K extends keyof T не даёт передать несуществующий ключ, а дальше mapped type собирает объект из выбранных полей.
Руками короче написать один раз, но производный тип живёт вместе с исходным: переименовали name в User, и Pick немедленно подсветит все места, где старый ключ ещё используется. Копия промолчит и разъедется с оригиналом.
Задача «взять всё, кроме перечисленного» решается через Omit, это следующее задание. Выбор между ними прагматичный: берёшь то, что короче и что лучше переживёт добавление новых полей в исходный тип.