Разбор с помощью шаблонных литералов
Извлекайте структурированные данные из строк с помощью infer
«Разбор с помощью шаблонных литералов» — бесплатный урок 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 — локальная установка не требуется.
Все уроки этого курса
- Основы комбинаторов анализаторов
- Разделение строк на уровне типов
- Разбор с помощью шаблонных литералов
- Мини-анализатор маршрутов на уровне типов