https://habr.com/ru/company/ruvds/blog/516304/- Блог компании RUVDS.com
- Разработка веб-сайтов
- JavaScript
- TypeScript
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?
