TypeScript — это язык, расширяющий JavaScript, добавляя в последний типизацию. Правда, так как TypeScript не имеет runtime-а (почти), он транслируется в JavaScript, в процессе чего, вся типизация теряется. Такую типизацию можно назвать лишь инструментом статического анализа кода. Тем не менее — это очень мощный инструмент. К тому же, помимо проверки кода, типизация также и документирует его. В данной статье я расскажу лишь про типы, объявленные через ключевое слово type, не касаясь интерфейсов и классов. Однако, эта тема шире, чем может показаться, и я надеюсь, что читатель узнает что-то новое для себя. Ведь с помощью type можно писать маленькие программки (далее, утилиты), которые выполняются в процессе статического анализа кода, расширяя его возможности. Множества. Самый простой способ использования ключевого слова type - объявление некоторого множества: Теперь рассмотрим пример использования утилиты Extract из стандартной библиотеки TypeScript (Built-in utility types). Имеем множества A и B. С помощью утилиты Extract получаем такое подмножество C, в которое входят те элементы из множества A, которые есть в множестве B: Теперь рассмотрим реализацию утилиты Extract. В утилитах для ветвления используется тернарный оператор ?:: Необходимо усвоить, что ключевое слово extends в данном случае представляет собой не только условие, но и неявный цикл, так как условие применяется для каждого элемента множества T, проверяя, принадлежит ли этот элемент множеству U. Также, обратите внимание на использование never. Тернарной оператор подразумевает строгое ветвление на if и else. Если какой-то из веток нет в логике, явно указываем это типом never. Часто используемый способ объявления множества из ключей объекта - ключевое слово keyof: Утилиты для объявления объектов. Объект через ключевое слово type можно объявить следующим образом: В данном случае, Keys - множество ключей объекта, а Values - множество типов значений объекта. Key в бинарном операторе in - объявление типа, в который в цикле будут подставляться элементы множества Keys. Для тренировки, попробуйте проанализировать следующий код: Далее, рассмотрим реализацию утилиты Partial. Для примера: Как видно, для решения задачи, используется суффикс ?. Собственно, для реализации Partial тоже задействован ? следующим образом: Убрать необязательность можно с помощью суффикс -?: Таким же образом можно убрать/добавить модификатор readonly: А для закрепления материала, рассмотрим утилиту, которая некоторые заданные свойства исходного типа делает readonly, а остальные - необязательными. Обратите внимание, что конечный тип объединяет в себе два типа с помощью оператора &: Работа с функциями Первый вид работы с функциями - получение типов аргументов функции или типа, возвращаемого функцией. К таким, например, относятся утилиты Parameters<Type>, ReturnType<Type> или InstanceType<Type>. Предположим, нужно написать утилиту, которая будет получать тип второго аргумента. Назовем ее SecondArg<Type>. Конечно, такую утилиту можно выразить через встроенную утилиту Parameters<Type>: Но для понимания работы Parameters<Type>, напишем реализацию "с нуля". В основе будет лежать тернарный оператор ?: и оператор extends: Оператор extends проверяет, является ли тип T функцией, в которой есть некоторый первый аргумент любого типа и второй аргумент типа U. Также у функции могут быть другие аргументы, но это не важно. Перед типом U стоит ключевое слово infer, означающее, что обобщенный (generic) тип U объявляется через выведение (inference) типа. Проверяем: Обратите внимание, что для типа B был выведен тип unknown, т.е. по сути any. Учтем это и поправим реализацию: Теперь рассмотрим другой способ работы с типами в функциях. Разберем такую функцию, возвращаемый тип которой выводится через аргумент: И запишем такое повевение в виде типа: Здесь обобщенный (generic) тип T объявляется cправa от =, что означает, что этот тип будет выводится. Рассмотрим пример, где это может использоваться. Допустим, у нас есть функции для получения каких-то моделей с сервера. Например: Также есть функция, которая запрашивает эти данные в какой-то момент времени и передает модели на обработку. Запишем тип: Использоваться функция типа DataProcess будет следующим образом: Заключение Конечно, в большинстве случаев можно (и нужно) обойтись объявлением типов через ключевое слово interface. Но иногда бывают хитрые ситуации, и типизация typescript способна предоставить мощные инструменты для решения нестандартных задач. Также не забывайте про стандартную библиотеку утилит при написании функций и методов. И да поможет вам статический анализ кода! ;)  Frontend разработчик