Includes
Проблема
Реализовать функцию Array.includes
из JavaScript в системе типов TypeScript.
Этот тип принимает два тип параметра. Результатом должно быть либо true
, либо
false
. Например:
// expected to be `false`
type isPillarMen = Includes<["Kars", "Esidisi", "Wamuu", "Santana"], "Dio">;
Решение
Начнём с типа, который принимает два тип параметра: T
(кортеж из элементов) и
U
(что мы ищем в кортеже).
type Includes<T, U> = never;
Прежде чем приступить к поиску в кортеже, облегчим себе жизнь и приведём кортеж
в объединение элементов. Для этого воспользуемся индексными типами. Используя
индексные типы, мы можем написать конструкцию T[number]
, результатом которой
будет объединение элементов из кортежа T
. Например, если у вас
T = [1, 2, 3]
, то результатом T[number]
будет 1 | 2 | 3
.
type Includes<T, U> = T[number];
Получаем ошибку “Type ‘number’ cannot be used to index type ‘T’”. У нас нету
никаких ограничений на T
, которые укажут что это массив. Поэтому TypeScript не
гарантирует, что обращение по индексу возможно. Починим это, указав, что T
-
массив.
type Includes<T extends unknown[], U> = T[number];
На этом этапе, у нас есть объединение элементов из кортежа T
. Как же
проверить, что элемент существует в объединении? Дистрибутивные условные типы!
Напишем условный тип для T[number]
и TypeScript проверит наше условие по
отношению к каждому элементу из объединения.
Например, если мы напишем 2 extends 1 | 2
, то TypeScript выполнит две проверки
2 extends 1
и 2 extends 2
. Проверим, что элемент, который мы ищем [U
],
находится в объединении элементов T
. В случае, элемент находится в объединении
элементов, мы возвращаем true
, иначе - false
.
type Includes<T extends unknown[], U> = U extends T[number] ? true : false;
Комментарии