Регулярные выражения в TypeScript: от теории к практике
Регулярные выражения (regex) — мощный инструмент для работы со строками. В TypeScript они не только позволяют выполнять поиск, замену и валидацию, но и обеспечивают строгую типизацию, что снижает количество ошибок на этапе компиляции. В этой статье мы разберём, как использовать регулярные выражения в TypeScript на реальных примерах: от валидации email до безопасного извлечения данных.
1. Создание и типизация регулярных выражений
В TypeScript регулярное выражение можно создать двумя способами: с помощью литерала или конструктора RegExp. Первый способ предпочтительнее, так как он короче и не требует экранирования обратных слешей.
// Литерал (рекомендуемый способ)
const emailRegex: RegExp = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
// Конструктор (полезен для динамических шаблонов)
const pattern: string = 'hello';
const dynamicRegex: RegExp = new RegExp(pattern, 'gi');
console.log(emailRegex.test('user@example.com')); // true
console.log(dynamicRegex.test('Hello, world!')); // true (флаг i игнорирует регистр)
Обратите внимание на аннотацию типа : RegExp. TypeScript автоматически выводит тип для литералов, но явное указание помогает документировать код.
2. Флаги и их типизация
Флаги изменяют поведение регулярного выражения. В TypeScript тип флагов может быть задан через строковый литерал или перечисление. Рассмотрим основные флаги:
- g — глобальный поиск (не останавливается после первого совпадения);
- i — регистронезависимый режим;
- m — многострочный режим (^ и $ работают для каждой строки);
- s — точка совпадает с символом новой строки;
- u — поддержка Unicode;
- y — поиск с последней найденной позиции (sticky).
// Типизация флагов через строку
const regexWithFlags: RegExp = /test/gim;
// Проверка флагов
console.log(regexWithFlags.flags); // "gim"
console.log(regexWithFlags.global); // true
console.log(regexWithFlags.ignoreCase); // true
console.log(regexWithFlags.multiline); // true
Для динамических флагов используйте тип string, но лучше ограничить его допустимыми значениями с помощью литерального объединения:
type RegexFlags = 'g' | 'i' | 'm' | 's' | 'u' | 'y';
const flags: RegexFlags = 'gi'; // Ошибка: 'gi' не является отдельным флагом
// Правильно: передавать строку
const dynamicFlags: string = 'gi';
const regex: RegExp = new RegExp('pattern', dynamicFlags);
3. Методы RegExp и типизация результатов
Основные методы для работы с регулярными выражениями в TypeScript:
test()— возвращаетboolean;exec()— возвращаетRegExpExecArray | null;match()— метод строки, возвращаетRegExpMatchArray | null;replace()— заменяет совпадения и возвращает строку;search()— возвращает индекс первого совпадения или -1.
Рассмотрим пример с exec(), который даёт доступ к группам захвата:
const dateRegex: RegExp = /(\d{4})-(\d{2})-(\d{2})/;
const dateStr: string = 'Сегодня 2025-03-15';
const match: RegExpExecArray | null = dateRegex.exec(dateStr);
if (match) {
const [fullMatch, year, month, day] = match;
console.log(`Год: ${year}, Месяц: ${month}, День: ${day}`);
// Вывод: Год: 2025, Месяц: 03, День: 15
} else {
console.log('Дата не найдена');
}
Обратите внимание: match[0] — это полное совпадение, а индексы 1, 2, 3 — группы захвата. TypeScript корректно выводит типы, если использовать деструктуризацию.
4. Практические примеры: валидация и парсинг
Теперь применим знания на реальных задачах. Рассмотрим три распространённых сценария.
4.1 Валидация email
Простая, но эффективная проверка формата email:
function validateEmail(email: string): boolean {
const emailPattern: RegExp = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/;
return emailPattern.test(email);
}
console.log(validateEmail('user@example.com')); // true
console.log(validateEmail('user@.com')); // false
console.log(validateEmail('user@example')); // false
4.2 Извлечение чисел из строки
Допустим, нужно найти все числа в тексте:
function extractNumbers(text: string): number[] {
const numberRegex: RegExp = /\d+/g;
return (text.match(numberRegex) || []).map(Number);
}
const result: number[] = extractNumbers('Цена: 1500 руб, скидка 10%');
console.log(result); // [1500, 10]
Метод match возвращает null, если совпадений нет, поэтому используем оператор || [] для безопасного преобразования.
4.3 Замена с использованием групп
Заменим формат даты с ISO на русский:
function formatDate(dateStr: string): string {
const dateRegex: RegExp = /(\d{4})-(\d{2})-(\d{2})/;
return dateStr.replace(dateRegex, '$3.$2.$1');
}
console.log(formatDate('Сегодня 2025-03-15')); // "Сегодня 15.03.2025"
В строке замены $1, $2, $3 ссылаются на группы захвата. TypeScript не проверяет корректность строки замены, поэтому будьте внимательны.
Заключение
Регулярные выражения в TypeScript — это не просто строковые шаблоны, а полноценные объекты с типизированными методами. Благодаря строгой типизации вы