Если вы когда-либо использовали TypeScript, вы должны знать хотя бы такие примитивные типы, как строка, число и логическое значение. Несмотря на то, что большую часть времени вы используете их напрямую или в качестве типов свойств интерфейса, вряд ли какое-либо приложение сможет избежать использования более продвинутых методов.
Каждый из этих типов имеет подробную документацию, доступную на официальном сайте и других онлайн-ресурсах. Я не хочу вас обманывать — большинство из них довольно хороши, но поиск в Google и статьях того, что мне нужно, всегда вызывает когнитивную перегрузку, которой мне хотелось бы избежать.
Я планирую добавить эту статью в закладки, как только она будет завершена, и использовать ее для дальнейшего использования, если я забуду (снова), как работают эти типы.
Общие типы
Обычно внутри функции мы уже знаем, какой тип она должна возвращать.
function sum(a: number, b: number): number { return a + b }
Однако все может быть иначе. Возможно, функция возвращает значения разных типов в зависимости от переданных аргументов. Рассмотрим таблицу с конфигурациями для внешних вызовов API, содержащую записи с двумя полями — slug и value.
Теперь, если вы хотите иметь функцию, которая извлекает значение конфигурации по пулу, она будет возвращать разные типы в зависимости от переданного пула. Вот тут-то и пригодится универсальный тип. Под универсальным типом можно понимать тип, передаваемый в качестве аргумента функции. Давайте продемонстрируем это:
function main(): void { const throttleLimit = getConfig<number>('throttle-limit') const apiEndpoint = getConfig<string>('api-endpoint') } function getConfig<T>(slug: string): T { return getValue(slug) // do whatever is needed to get the value from db }
Синтаксис может быть не очень интуитивным, но он все равно прост. Когда вы вызываете функцию, которая ожидает универсальный тип, вы передаете ее в угловых скобках между именем функции и аргументами, например:
getConfig‹number('ограничение скорости')
А затем оно снова фиксируется в функции между именем и аргументами:
getConfig‹T›(слаг: строка).
Называть его «T» – это просто общепринятое соглашение; вы можете использовать любое другое имя. В конце концов его можно будет использовать так же, как и любые другие типы внутри функции.
Типы союзов
Это представляет собой очень простую концепцию. С точки зрения синтаксиса это просто вертикальная черта “|” символ, который можно прочитать как логический оператор ИЛИ (||). Мы можем использовать предыдущий пример и переписать его следующим образом:
function main(): void { const throttleLimit = getConfig('throttle-limit') const apiEndpoint = getConfig('api-endpoint') } function getConfig(slug: string): string | number { return getValue(slug) // do whatever is needed to get the value from db }
Конечно, это не идеальное решение для производства, поскольку значения могут быть разных типов.
Типы пересечений
Документация: Типы пересечений
Если типы объединения аналогичны логическому оператору ИЛИ, то типы пересечения аналогичны логическому оператору И. Распространенный случай использования возникает, когда у вас есть стандартный интерфейс, описывающий объект, но в конкретном сценарии вам необходимо расширить его новыми полями.
function supplyWithCallsLeft(apiResponse): Response & {callsLeft: number} => { return { ...Response, callsLeft: Response.ApiCallsLimit - Response.ApiCallsCount } }
Очевидно, что Ответ не должен содержать вычисленные значения, подобные этому; следовательно, и соответствующий интерфейс. Но если вам нужно что-то подобное, вам пригодятся типы пересечений.
Сопоставленные типы
Документация: Сопоставленные типы
Для тех, кто относительно плохо знаком с TypeScript, отображаемые типы могут оказаться весьма привлекательными.
Представьте себе типичную ситуацию: у вас есть старомодный объект «ключ-значение», и вы не знаете, какие именно ключи будут использоваться, но знаете их типы.
type Mapping = { [key: string]: string }
Этот тип будет охватывать следующий пример:
const animalsToSizeMapping: Mapping = { 'dog' : 'big', 'cat' : 'small, 'mouse': 'tiny' }
Не ожидайте, что ваше отображение будет настолько хорошим, но, скорее всего, есть вещи, которые вы захотите отобразить в своем приложении.
Типы строковых литералов
Документация: Литеральные типы
Вероятно, самый простой, но из-за его очень специфического поведения в некоторых случаях он может быть очень полезен. Идея проста: в то время как тип string проверяет, является ли значение какой-либо строкой, тип строковый литерал проверяет, является ли значение точной строкой. . Давайте последуем предыдущему примеру и определим тип животных:
type Animal = 'dog' | 'cat' | 'mouse'
Эта функция будет работать нормально:
function speak(animal: Animal) { if(animal === 'dog') { console.log('woof-woof') } if(animal === 'cat') { console.log('meow-meow') } if(animal === 'mouse') { console.log('pi-pi-pi') } }
Но добавление чего-либо из списка приведет к ошибке TypeScript:
function speak(animal: Animal) { if(animal === 'dog') { console.log('woof-woof') } if(animal === 'cat') { console.log('meow-meow') } if(animal === 'mouse') { console.log('pi-pi-pi') } if(animal === 'frog') { // TypeScript would tell you that 'Animal' and '"frog"' have no overlap console.log('croak-croak') }
Очевидно, это может уберечь вас от ошибок в написании и предоставить некоторую документацию по коду. Это также помогает при моделировании концепций, специфичных для предметной области, с ограниченным набором возможных значений.
Заключение
Изучение новых концепций и освоение TypeScript открывает различные возможности для решения задач, используя на выходе хороший и читаемый код, вместо того, чтобы полагаться на банальные методы.
Я советую вам найти больше полезных функций TypeScript и поделиться ими в разделе комментариев!
Стеккадемический
Спасибо, что дочитали до конца. Прежде чем уйти:
- Пожалуйста, рассмотрите возможность аплодировать и следовать автору! 👏
- Следуйте за нами в Twitter(X), LinkedIn и YouTube.
- Посетите Stackademic.com, чтобы узнать больше о том, как мы демократизируем бесплатное образование в области программирования во всем мире.