TypeScript Academy · Урок

Разбор с помощью шаблонных литералов

Извлекайте структурированные данные из строк с помощью infer

Урок 3 из 413 шагов

«Разбор с помощью шаблонных литералов» — бесплатный урок TypeScript Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения TypeScript Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс TypeScript Academy содержит 4 уроков всего.

От разбиения к структуре

Разбиение даёт кортеж частей. Разбор идёт дальше: он извлекает именованные структурированные данные из строкового типа. Мы используем шаблоны шаблонных строк с несколькими переменными infer, чтобы получить нужные нам части.

Обозначения: в настоящем TypeScript шаблонные строковые типы записываются строками, ограниченными обратными кавычками и содержащими места для подстановок с долларом и фигурными скобками. В этих фрагментах мы показываем такой шаблон в виде Tpl<...>, перечисляя его части по порядку; например, шаблон в обратных кавычках, сопоставляющий сначала литеральный префикс, а затем Rest, выглядит как Tpl<'prefix', infer Rest>.

type KeyValue<S> =
  S extends Tpl<infer K, '=', infer V> ? { key: K; value: V } : never;
// Tpl<K, '=', V> matches K, an equals sign, then V

type X = KeyValue<'name=alice'>; // { key: 'name'; value: 'alice' }

Несколько точек вывода

Один шаблон может одновременно захватывать несколько полей. Чтобы разобрать "GET /users", выведите метод и путь в одном условии.

type Request<S> =
  S extends Tpl<infer Method, ' ', infer Path>
    ? { method: Method; path: Path }
    : never;
// Tpl<Method, ' ', Path> matches the method, a space, then the path

type X = Request<'GET /users'>; // { method: 'GET'; path: '/users' }

Сужение выведенных частей

Можно встроенно ограничить выведенную переменную с помощью extends, чтобы она сопоставлялась только с определёнными формами. В данном случае метод должен быть известным глаголом.

type Method = 'GET' | 'POST';
type Parse<S> =
  S extends Tpl<(infer M extends Method), ' ', infer P>
    ? { method: M; path: P }
    : never;
// the inferred M is constrained to Method inside the template pattern

type X = Parse<'POST /x'>; // { method: 'POST'; path: '/x' }

Разбор пар ключ-значение

Объедините разбиение и разбор: разделите строку запроса на пары, а затем разберите каждую пару на ключ и значение. В результате получится кортеж структурированных записей.

type Pair<S> =
  S extends Tpl<infer K, '=', infer V> ? [K, V] : [S, ''];
// Tpl<K, '=', V> splits a 'key=value' string literal type

type X = Pair<'page=2'>; // ['page', '2']

Построение объекта из пар

Сверните кортеж пар ключ-значение в тип объекта с помощью аккумулятора на основе отображения и пересечения. Каждая пара добавляет одно свойство.

type FromPairs<T extends [string, string][]> =
  T extends [[infer K extends string, infer V], ...infer R extends [string, string][]]
    ? { [P in K]: V } & FromPairs<R>
    : {};

type X = FromPairs<[["a", "1"], ["b", "2"]]>; // { a: "1" } & { b: "2" }

Разбор строки запроса

Объедините всё: разделите строку по "&", разберите каждый фрагмент по "=", а затем постройте объект. Теперь компилятору известны точные ключи строкового литерала запроса.

type ParseQuery<S extends string> =
  FromPairs<{ [I in keyof SplitAmp<S>]: Pair<SplitAmp<S>[I] & string> }>;
// where SplitAmp splits on "&" (from previous lesson)

Извлечение чисел

Выведенные части всегда имеют типы строковых литералов. Чтобы трактовать часть как число, проверьте, соответствует ли она числовому шаблону, или преобразуйте её с помощью ограничения только для digits. Значение при этом остаётся типом-литералом.

type IsNumeric<S extends string> =
  S extends Tpl<number> ? true : false;
// Tpl<number> is a template literal type that matches any numeric string

type X = IsNumeric<'42'>; // true
type Y = IsNumeric<'4a'>; // false

Необязательные сегменты

Используйте объединение шаблонов для обработки необязательных частей. Сначала попробуйте более подробный шаблон, а если он не сопоставится, перейдите к более простому варианту.

type ParsePath<S> =
  S extends Tpl<infer Base, '?', infer Query>
    ? { base: Base; query: Query }
    : { base: S; query: '' };
// Tpl<Base, '?', Query> matches an optional query after a question mark

type X = ParsePath<'/x?a=1'>; // { base: '/x'; query: 'a=1' }

Пробелы и особые случаи

В настоящих строках встречаются лишние пробелы. Объедините анализатор с типом Trim из предыдущего урока, чтобы начальные и конечные пробелы не искажали извлечённые поля.

type CleanKey<S extends string> = Trim<S>;
// Apply Trim to each inferred segment before using it

Почему это мощный подход

Разбор с помощью шаблонных строк позволяет компилятору понимать форматы: даты, маршруты, ключи переменных окружения и фрагменты SQL. Строки с ошибками превращаются в ошибки компиляции, а последующие типы могут зависеть от разобранной структуры. Строковый литерал становится типизированным значением.

type Event<S> =
  S extends Tpl<infer Domain, ':', infer Action>
    ? { domain: Domain; action: Action }
    : never;
// Tpl<Domain, ':', Action> matches 'domain:action'
type X = Event<'user:created'>; // { domain: 'user'; action: 'created' }

Объединение анализаторов

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

// Split -> Pair -> FromPairs is a parser pipeline at the type level

Быстрая проверка

Проверьте, насколько хорошо Вы понимаете разбор с помощью шаблонных строк.

Итоги

Вы извлекли структурированные данные из строковых типов.

  • Несколько точек infer захватывают именованные поля в одном шаблоне.
  • Выведенные части можно сузить с помощью встроенного extends.
  • Разбиение, пара и FromPairs объединяются в анализатор запросов.
  • Удаление пробелов и проверки чисел обрабатывают особые случаи.

Далее: полноценный небольшой анализатор маршрутов.

Можно начать бесплатно

Изучай TypeScript с ИИ-репетитором — бесплатно

Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.

Курсы
101
Уроки
352

Часто задаваемые вопросы

Урок «Разбор с помощью шаблонных литералов» бесплатный?

Да — полный текст урока «Разбор с помощью шаблонных литералов» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс TypeScript Academy, подпишись на CoddyKit PRO. Курс TypeScript Academy содержит 4 уроков всего.

Чему я научусь в уроке «Разбор с помощью шаблонных литералов»?

Извлекайте структурированные данные из строк с помощью infer Ты практикуешь TypeScript Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать TypeScript Academy?

Предыдущий опыт не требуется. TypeScript Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Разбор с помощью шаблонных литералов»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке TypeScript Academy?

Да. Каждый урок TypeScript Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Основы комбинаторов анализаторов
  2. Разделение строк на уровне типов
  3. Разбор с помощью шаблонных литералов
  4. Мини-анализатор маршрутов на уровне типов
← Назад к TypeScript Academy