PickByType
Завдання
З вхідного параметру T
виберіть ті властивості, які можна привласнити до U
.
Наприклад:
type OnlyBoolean = PickByType<
{
name: string;
count: number;
isReadonly: boolean;
isEnable: boolean;
},
boolean
>; // { isReadonly: boolean; isEnable: boolean; }
Розв’язок
В цій проблемі нам потрібно перебрати всі ключі об’єкта. В момент перебору, нам
потрібно відфільтрувати й залишити тільки ті ключі, які можна привласнити до
U
. Очевидно, що почати нам потрібно з типів зіставлення.
Так що давайте почнемо з того, що зробимо копію вхідного об’єкту:
type PickByType<T, U> = { [P in keyof T]: T[P] };
Спочатку, ми отримали всі ключі з T
й застосували до них ітерацію. Під час
кожної ітерації, TypeScript візьме ключ й привласнить його до тип параметру P
.
Маючи цей ключ, ми можемо отримати потрібний нам тип з використанням конструкції
T[P]
.
Тепер, застосовуючи фільтр до цієї ітерації, ми можемо залишити тільки потрібні нам ключі. Коли я кажу “фільтр”, я маю на увазі перевизначення ключа в цій ситуації. Ми можемо перевизначити ключ під час кожної ітерації й залишити тільки ті що нас цікавлять:
type PickByType<T, U> = {
[P in keyof T as T[P] extends U ? never : never]: T[P];
};
Зверніть увагу на ключове слово as
. Це оператор, який замінить наший тип P
на тип вказаний за допомогою as
. І нас нічого не зупиняє від того, щоб
написати умовний тип після as
. За допомогою умовного типу ми й перевіримо нашу
умову.
У випадку, якщо тип значення із об’єкту привласнюється до типу, який вказаний в
U
- залишаємо ключ без змін. Але, якщо тип не привласнюється, то в такому
випадку ми повинні його ігнорувати - повертаємо never
:
type PickByType<T, U> = { [P in keyof T as T[P] extends U ? P : never]: T[P] };
Таким чином, ми реалізували тип, який може фільтрувати ключ об’єктів по їх типам.
Коментарі