Pull to refresh
2676.2
RUVDS.com
VDS/VPS-хостинг. Скидка 15% по коду HABR15

В TypeScript 4.0 наконец появилось то, чего я очень ждал

Reading time 3 min
Views 22K
Original author: Nathaniel Kessler
6 августа сего года Microsoft объявила о выходе релиз-кандидата TypeScript 4.0. Там появилась поддержка кортежей с маркированными элементами (Labeled Tuple Elements). А это — именно то, появления чего я ждал в TypeScript.


Наверху — аргументы, которым назначены содержательные метки. Внизу — аргументы с бесполезными именами

Почему я этого ждал? Объясню это на примере разработки функции.

Обобщённый интерфейс, поддерживающий гибкую работу с аргументами


Вот — упрощённый пример. Он основан на использовании интерфейса IQuery. Интерфейс предназначен для описания характеристик функций, выполняющих запросы на получение чего-либо. Он всегда возвращает промис и принимает дженерик, описывающий то, что возвращает промис (TReturn). Этот интерфейс достаточно гибок, им можно пользоваться при создании функций, не принимающих никаких аргументов, или принимающих неизвестное количество аргументов (UParams extends any[] = []).

interface IQuery<TReturn, UParams extends any[] = []> {
  (...args: UParams): Promise<TReturn>
}

Исследуемая функция: findSongAlbum()


Мы, используя этот интерфейс, напишем функцию, которая ищет музыкальные альбомы по названию композиции (title) и по исполнителю (artist). Она возвращает промис, который выдаёт единственный объект типа Album:

type Album = {
  title: string
}

Без использования TypeScript код подобной функции мог бы выглядеть так:

const findSongAlbum = (title, artist) => {
  // код загрузки данных...
  
  const albumName = '1989';
  return Promise.resolve({
     title: albumName
  });
}

Если же написать такую функцию на TypeScript и воспользоваться при этом интерфейсом IQuery, то в качестве первого дженерик-параметра ей нужно передать тип Album. Это позволяет обеспечить то, что форма того, что возвращает промис, всегда будет соответствовать типу Album.

const findSongAlbum: IQuery<Album> = (title, artist) => {
  // код загрузки данных...
  
  const albumName = '1989';
  return Promise.resolve({
     title: albumName 
  });
}

Код, который писали до TypeScript 4.0


При разработке нашей функции ещё нужно объявить параметры и указать то, какие типы они имеют. В данном случае title и artist — это строки. Объявим новый тип, Params, и передадим его в качестве второго типа для IQuery.

В том примере, который написан без использования новых возможностей TypeScript 4.0, Params будет представлен списком типов. Каждый элемент этого списка определяет тип аргумента. Делается это в том же порядке, в котором аргументы располагаются при объявлении функции. Это — пример использования кортежей.

type Params: [string, string]
const findSongAlbum: IQuery<Album, Params> = (title, artist) => {
  // код загрузки данных...
  
  const albumName = '1989';
  return Promise.resolve({
     title: albumName
  });
}

Анализируя тип Params, можно узнать о том, что его первый элемент, string, назначает тип string первому аргументу, то есть — title. Второй аргумент, тоже выглядящий как string, естественно, следуя тому же ходу рассуждений, назначает тип string второму аргументу — artist. Это обеспечит типобезопасную работу со списком аргументов.

Попробуем поработать с этой функцией.


В подсказках к findSongAlbum() выводятся бессмысленные метки аргументов

К сожалению, подобный подход к использованию кортежей не даёт нам полезных и способствующих написанию надёжного кода имён (меток) аргументов при работе с функцией. Вместо этого нам сообщают о том, что аргументами функции являются args_0: string, args_1: string. Из этого сообщения я могу узнать, например, лишь о том, что первый аргумент должен иметь тип string. Метка arg_0 не даёт мне сведений о том, что первым параметром функции должно быть название (title) музыкальной композиции, которую я ищу.

Код, в котором используются возможности TypeScript 4.0


Теперь, с выходом релиз-кандидата TypeScript 4.0, в нашем распоряжении оказываются кортежи с маркированными элементами. Их мы можем использовать для того чтобы описывать не только тип, но и смысловое содержание списков параметров функций.

Теперь каждый элемент типа Params будет снабжён меткой, которая будет выводиться в IDE при использовании функции findSongAlbum:

type Params: [title: string, artist: string]
const findSongAlbum: IQuery<Album, Params> = (title, artist) => {
  // код загрузки данных...
  
  const albumName = '1989';
  return Promise.resolve({
     title: albumName
  });
}

А вот как выглядит работа с этой функцией.


В подсказках к findSongAlbum() выводятся метки аргументов, позволяющие понять смысл этих аргументов, что весьма полезно

Как видите, теперь, вместо подсказки вида arg_0: string нам дают подсказку title: string. А это значит, что мы теперь знаем не только о том, что функции надо передать строку, но и о том, что именно должна содержать эта строка.

Чего вам особенно не хватает в TypeScript?

Tags:
Hubs:
+38
Comments 41
Comments Comments 41

Articles

Information

Website
ruvds.com
Registered
Founded
Employees
11–30 employees
Location
Россия
Representative
ruvds