TS Extend: полезная утилитарная функция для расширения type

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

В текущей версии TS (5.7) нет нативного расширения типов.

Расширение в TS реализуют интерфейсы через ключевое слово extend, причем интерфейсы могут быть расширены только от одного объекта.

Хотя для типов (type/interface) предусмотрена операция интерсекции (&), которая объединяет свойства двух или более типов - она обладает важным ограничивающим свойством - при наличии одинаковых свойств, операция интерсекции присваивает их результирующему типу значение never.

Если же мы хотим, чтобы свойство перезаписывалось последним значением пересечения, мы можем написать утилитарную функцию Extend, которая примет в себя массив типов, объединит их, а при наличии свойств с одинаковым именем, запишет в конечное значение последнее из них.

Тип ExtendType будет выглядеть так:

type ExtendType<A extends any[]> = A extends [infer T1, infer T2, ...infer R] ? Omit<T1, keyof T2> & T2 & ExtendType<R> : unknown;

Давайте разберем этот тип.

Так ExtendType принимает A массив типов:

type ExtendType<A extends any[]>

дальше, разбивает его на типы T1, T2 и R:

type ExtendType<A extends any[]> = A extends [infer T1, infer T2, ...infer R]

затем, удаляет из T1 все одинаковые с T2 ключи и возвращет unknown, если на вход не был получен массив:

type ExtendType<A extends any[]> = A extends [infer T1, infer T2, ...infer R] ? Omit<T1, keyof T2> : unknown

после, соединяет результат операции удаления с T2, таким образом, по сути, перезатирая ключи T1 ключами T2:

type ExtendType<A extends any[]> = A extends [infer T1, infer T2, ...infer R] ? Omit<T1, keyof T2> & T2 : unknown

Наконец, выше описанная операция повторяется рекурсивно:

type ExtendType<A extends any[]> = A extends [infer T1, infer T2, ...infer R] ? Omit<T1, keyof T2> & T2 & ExtendType<R> : unknown;

Также для чистого вывода при навередении на тип в IDE, мы можем написать еще одну утилитарную функцию - Pretty, которая линейно переберет все ключи получившегося типа с присвоенными значениями:

export type Pretty<T> = { [K in keyof T]: T[K]; } & {};

По сути, результат типа Extend никак не измениться, но так будет проще читать тип. В итоге, экспортируемый тип Extend будет выглядеть так:

export type Extend<A extends any[]> = Pretty<ExtendType<A>>;

К примеру, так создание типа SuperUser, объединенного из типов:

type User = {
  id: number;
  name: string;
}

type SuperData = {
  token: string;
  fullAccess: boolean;
}

будет выглядеть так:

type SuperUser = Extend<[User, SuperData]>;

Так в Extend можно передать любое количество типов, и, если нужно, добавить и перезаписать что-то, то можно просто передать еще тип в функцию:

type SuperUser = Extend<[User, SuperData, {
  id: number | string;
  fullAccess?: boolean;
}]>;

Полученный в результате тип SuperUser будет таким:

id: number | string;
name: string;
token: string;
fullAccess?: boolean;

Также, если вы используете VSCode - вы можете добавть код обьявления типа Extend в сниппет в файле typescript-а:

и добавить следующий json-сниппет:

  "UTILS TYPE EXTEND PRETTY": {
    "prefix": "utep",
    "body": [
      "${1:export }type Pretty<T> = { [K in keyof T]: T[K]; } & {};",
      "",
      "type ExtendType<A extends any[]> = A extends [infer T1, infer T2, ...infer R] ? Omit<T1, keyof T2> & T2 & ExtendType<R> : unknown;${0}",
      "",
      "${1:export }type Extend<A extends any[]> = Pretty<ExtendType<A>>;",
      "${0}"
    ]
  },

Так при сочентании клавишь ute в .ts файле у вас будет готовая утилита слияния типо Extend.

Источник: https://habr.com/ru/articles/866400/


Интересные статьи

Интересные статьи

По информации издания Cnews, Роскомнадзор планирует до 2035 года создать в России собственную инфраструктуру для валидации маршрутизации IP-адресов. Эксперты пояснили, что речь в данном случае идёт о ...
1С-Битрикс официально присвоил Digital HR компания «Улей» максимальный уровень компетенции «Крупные корпоративные внедрения». Компетенция подтверждает профессиональные навыки компании в разработк...
Создадим прототип SPA в Bitrix без использования популярных JS фреймворков и библиотек, все будет сделано средставами Bitrix.И самое главное без потери серверного рендеринга и SEO страниц.ПогналиВсего...
Начиналось всё с системника в общаге МГУ и обычного хостинга, на котором наше расписание электричек, которое многие из вас видели. И перекладывания файлов по ночам, чтобы уложиться в ...
Некоторое время назад мне довелось пройти больше десятка собеседований на позицию php-программиста (битрикс). К удивлению, требования в различных организациях отличаются совсем незначительно и...