Тип string в TypeScript
Строки, шаблонные строки и методы строк
Добро пожаловать!
Строки — это один из самых важных типов данных в программировании. С их помощью мы работаем с текстом: имена пользователей, сообщения, URL-адреса, сообщения об ошибках — всё это строки. В этом уроке мы детально изучим тип string в TypeScript, научимся создавать строки различными способами, работать с шаблонными строками и использовать богатый набор методов строк.
Цели урока
Что такое тип string?
Тип string представляет собой последовательность символов, заключённую в кавычки. В TypeScript строки могут быть созданы тремя способами: с помощью одинарных кавычек, двойных кавычек или обратных кавычек (для шаблонных строк).
Пример: Создание строк
// Одинарные кавычки
let имя: string = 'Иван';
let город: string = 'Москва';
// Двойные кавычки
let фамилия: string = "Петров";
let email: string = "user@example.com";
// Обратные кавычки (шаблонные строки)
let приветствие: string = `Привет, ${имя}!`;
console.log(имя); // "Иван"
console.log(приветствие); // "Привет, Иван!"
Совет
В современном JavaScript/TypeScript рекомендуется использовать одинарные или двойные кавычки для обычных строк и обратные кавычки только когда нужна шаблонная строка или многострочность.
Литералы строк и экранирование
В строках часто нужно вставлять специальные символы: кавычки, переносы строк, табуляции и другие. Для этого используются escape-последовательности.
Экранированные символы
// Экранирование кавычек
let кавычки1: string = "Он сказал: \"Привет!\"";
let кавычки2: string = 'Он сказал: \'Привет!\'';
// Специальные символы
let перевод: string = "Строка 1\nСтрока 2";
let таб: string = "Кол1\tКол2\tКол3";
let слэш: string = "Путь: C:\\Users\\Documents";
// Unicode символы
let сердце: string = "\u2764"; // ❤
let сперва: string = "\u0048\u0065\u006C\u006C\u006F"; // "Hello"
// Hex escape
let символ: string = "\x48"; // "H"
console.log(кавычки1); // Он сказал: "Привет!"
console.log(перевод); // Строка 1
// Строка 2
Таблица escape-последовательностей
| Последовательность | Описание | Пример |
|---|---|---|
\n |
Перенос строки | "Строка1\nСтрока2" |
\t |
Табуляция | "Кол1\tКол2" |
\\ |
Обратный слэш | "C:\\Путь" |
\" |
Двойная кавычка | "Сказал: \"Привет\"" |
\' |
Одинарная кавычка | 'It\'s' |
Шаблонные строки (Template Literals)
Шаблонные строки — это одна из самых мощных функций современного JavaScript/TypeScript. Они позволяют вставлять выражения прямо в строку и создавать многострочные тексты без использования переносов.
Интерполяция выражений
// Простая интерполяция
let имя: string = "Иван";
let возраст: number = 25;
// Конкатенация (старый способ)
let приветствие1: string = "Привет, " + имя + "! Тебе " + возраст + " лет.";
// Шаблонная строка (новый способ)
let приветствие2: string = `Привет, ${имя}! Тебе ${возраст} лет.`;
// Вычисления внутри ${}
let цена: number = 100;
let количество: number = 3;
let итого: string = `Итого: ${цена * количество} руб.`;
// Вызов функций внутри ${}
let большое: string = `Максимум: ${Math.max(10, 20, 30)}`;
// Тернарный оператор
let возрастКатегория: string = `Категория: ${возраст >= 18 ? "взрослый" : "ребёнок"}`;
console.log(приветствие2); // "Привет, Иван! Тебе 25 лет."
console.log(итого); // "Итого: 300 руб."
console.log(большое); // "Максимум: 30"
console.log(возрастКатегория); // "Категория: взрослый"
Многострочные строки
// Многострочная строка с обратными кавычками
let html: string = `
${имя}
Возраст: ${возраст}
`;
// Тоже работает с переносами строк
let poem: string = `
Мороз и солнце; день чудесный!
Ещё ты дремлешь, друг прелестный —
Пора, красавица, проснись:
Открой сомкнуты негой взоры
Навстречу северной Авроры,
Звездою севера явись!
`;
console.log(html);
Сравнение способов
| Способ | Преимущества | Недостатки |
|---|---|---|
+ конкатенация |
Простой синтаксис | Многословно, ошибки при сложных строках |
\`\${}\` шаблоны |
Читаемость, многострочность | Нет |
Свойства и методы строк
Строки в JavaScript/TypeScript имеют множество встроенных методов для работы с текстом. Давайте рассмотрим самые важные из них.
Свойство length
let строка: string = "Привет";
console.log(строка.length); // 6
// Пустая строка
console.log("".length); // 0
// С пробелами
console.log(" hello ".length); // 7 (включая пробелы)
// Unicode эмодзи
console.log("😀".length); // 2 (!) — эмодзи занимают 2 символа
console.log("Привет".length); // 6
Внимание: Свойство length может давать неожиданные результаты с эмодзи и некоторыми Unicode-символами. Для правильной работы с Unicode используйте методы Array.from() или [...str].
Методы регистра
let текст: string = "Hello, World!";
// toUpperCase() — в верхний регистр
console.log(текст.toUpperCase()); // "HELLO, WORLD!"
// toLowerCase() — в нижний регистр
console.log(текст.toLowerCase()); // "hello, world!"
// toLocaleUpperCase() — с учётом локали
console.log("istanbul".toLocaleUpperCase('tr')); // "İSTANBUL"
// toLocaleLowerCase() — с учётом локали
console.log("ISTANBUL".toLocaleLowerCase('tr')); // "istanbul"
// Практический пример: сравнение без учёта регистра
function сравнитьБезРегистра(a: string, b: string): boolean {
return a.toLowerCase() === b.toLowerCase();
}
console.log(сравнитьБезРегистра("Hello", "hello")); // true
console.log(сравнитьБезРегистра("TypeScript", "typescript")); // true
Методы поиска
let текст: string = "TypeScript — это круто!";
// indexOf() — возвращает индекс первого вхождения или -1
console.log(текст.indexOf("Script")); // 4
console.log(текст.indexOf("Java")); // -1 (не найдено)
// lastIndexOf() — индекс последнего вхождения
let много: string = "abcabc";
console.log(много.indexOf("b")); // 1
console.log(много.lastIndexOf("b")); // 4
// includes() — проверяет, содержит ли строка подстроку
console.log(текст.includes("Script")); // true
console.log(текст.includes("Python")); // false
// startsWith() — проверяет, начинается ли строки с подстроки
console.log(текст.startsWith("Type")); // true
console.log(текст.startsWith("Script")); // false
// endsWith() — проверяет, заканчивается ли строка подстрокой
console.log(текст.endsWith("круто!")); // true
console.log(текст.endsWith("Type")); // false
// search() — ищет по регулярному выражению
console.log(текст.search(/Script/)); // 4
console.log(текст.search(/python/i)); // -1
Методы извлечения подстрок
let строка: string = "Hello, World!";
// slice() — извлекает подстроку
console.log(строка.slice(0, 5)); // "Hello"
console.log(строка.slice(7)); // "World!"
console.log(строка.slice(-6)); // "orld!"
// substring() — похож на slice, но не принимает отрицательные индексы
console.log(строка.substring(0, 5)); // "Hello"
console.log(строка.substring(7)); // "World!"
// substr() (устаревший, не рекомендуется)
console.log(строка.substr(7, 5)); // "World"
//charAt() — символ по индексу
console.log(строка.charAt(0)); // "H"
console.log(строка[0]); // "H" (тоже работает)
// charCodeAt() — код символа
console.log(строка.charCodeAt(0)); // 72 (код "H")
console.log(строка.charCodeAt(6)); // 87 (код "W")
Методы обрезки пробелов
let сПробелами: string = " Hello, World! ";
// trim() — обрезает пробелы с обеих сторон
console.log(`[${сПробелами.trim()}]`); // "[Hello, World!]"
// trimStart() — обрезает пробелы в начале
console.log(`[${сПробелами.trimStart()}]`); // "[Hello, World! ]"
// trimEnd() — обрезает пробелы в конце
console.log(`[${сПробелами.trimEnd()}]`); // "[ Hello, World!]"
// Практический пример: валидация ввода
function валидироватьВвод(ввод: string): string {
const обработанный = ввод.trim();
if (обработанный.length === 0) {
throw new Error("Ввод не может быть пустым");
}
return обработанный;
}
console.log(валидироватьВвод(" admin ")); // "admin"
Методы замены
let текст: string = "Hello World! Hello TypeScript!";
// replace() — заменяет первое вхождение
console.log(текст.replace("Hello", "Привет"));
// "Привет World! Hello TypeScript!"
// replaceAll() — заменяет все вхождения
console.log(текст.replaceAll("Hello", "Привет"));
// "Привет World! Привет TypeScript!"
// Замена с регулярным выражением
console.log(текст.replace(/Hello/g, "Привет"));
// "Привет World! Привет TypeScript!"
// Разбор email
let email: string = "user@example.com";
let [имяПользователя, домен] = email.split("@");
console.log(имяПользователя); // "user"
console.log(домен); // "example.com"
// Разбор пути к файлу
let путь: string = "/home/user/document.txt";
let файл = путь.split("/").pop();
console.log(файл); // "document.txt"
Методы повторения и дополнения
// repeat() — повторяет строку N раз
let тире: string = "-".repeat(20);
console.log(tire); // "--------------------"
let звёзды: string = "*".repeat(5);
console.log(звёзды); // "*****"
// padStart() — дополняет строку до нужной длины в начале
let номер: string = "42";
console.log(номер.padStart(5, "0")); // "00042"
// padEnd() — дополняет строку в конце
let имя: string = "Иван";
console.log(имя.padEnd(20, ".")); // "Иван................."
// Практический пример: форматирование таблицы
function отформатироватьСтроку(
текст: string,
ширина: number,
выравнивание: "left" | "right" = "left"
): string {
if (выравнивание === "right") {
return текст.padStart(ширина);
}
return текст.padEnd(ширина);
}
console.log(отформатироватьСтроку("Имя", 15));
console.log(отформатироватьСтроку("123", 15, "right"));
Разделение и объединение строк
Методы split() и join() позволяют превращать строки в массивы и обратно.
// split() — разделение строки на массив
let csv: string = "яблоко,банан,апельсин";
let фрукты: string[] = csv.split(",");
console.log(фрукты); // ["яблоко", "банан", "апельсин"]
// Разделение по регулярному выражению
let текст: string = "Hello World TypeScript";
let слова: string[] = текст.split(/\s+/);
console.log(слова); // ["Hello", "World", "TypeScript"]
// Разделение по символу
let путь: string = "/home/user/file.txt";
let части: string[] = путь.split("/");
console.log(части); // ["", "home", "user", "file.txt"]
// Ограничение количества разделений
let ограниченный: string[] = csv.split(",", 2);
console.log(ограниченный); // ["яблоко", "банан"]
// join() — объединение массива в строку
let обратно: string = фрукты.join(", ");
console.log(обратно); // "яблоко, банан, апельсин"
// Практический пример: реверс строки
function реверсСтроки(строка: string): string {
return строка.split("").reverse().join("");
}
console.log(реверсСтроки("Hello")); // "olleH"
console.log(реверсСтроки("TypeScript")); // "tpircSepyT"
Unicode и эмодзи
Работа с Unicode и эмодзи может вызывать сложности, потому что некоторые символы занимают больше одного 16-битного слова в JavaScript.
// Проблема с эмодзи
let эмодзи: string = "😀🎉🚀";
console.log(эмодзи.length); // 6 (а не 3!)
console.log(эмодзи[0]); // "�" (сломанный символ)
// Решение 1: Array.from()
let символы: string[] = Array.from(эмодзи);
console.log(символы); // ["😀", "🎉", "🚀"]
console.log(символы.length); // 3
// Решение 2: Spread operator
let символы2: string[] = [...эмодзи];
console.log(символы2); // ["😀", "🎉", "🚀"]
// Решение 3: for...of
for (const символ of эмодзи) {
console.log(символ); // "😀", "🎉", "🚀"
}
// Unicode code points
let сердце: string = "❤️";
console.log(сердце.codePointAt(0)); // 10084
console.log(String.fromCodePoint(10084)); // "❤️"
// Проверка на эмодзи
function являетсяэмодзи(символ: string): boolean {
const регулярка = /[\u{1F600}-\u{1F64F}]/u;
return регулярка.test(символ);
}
console.log(являетсяэмодзи("😀")); // true
console.log(являетсяэмодзи("A")); // false
Сравнение строк
Строки в JavaScript сравниваются посимвольно на основе их Unicode значений. Это важно понимать для корректной сортировки и сравнения.
// Лексикографическое сравнение
console.log("а" > "б"); // false ( код 'а' = 1072, 'б' = 1073)
console.log("А" > "а"); // false (код 'А' = 1040, 'а' = 1072)
console.log("abc" < "abd"); // true
console.log("abc" < "ab"); // false
// Сравнение с учётом локали
let строки: string[] = ["в", "а", "г", "б"];
console.log(строки.sort()); // ["а", "б", "в", "г"] (русские)
// Локализованная сортировка
let города: string[] = ["Москва", "Санкт-Петербург", "Казань", "Новосибирск"];
console.log(города.sort((a, b) => a.localeCompare(b, 'ru')));
// ["Казань", "Москва", "Новосибирск", "Санкт-Петербург"]
// localeCompare с опциями
let имена: string[] = ["Иван", "иван", "ИВАН"];
console.log(имена.sort((a, b) => a.localeCompare(b, 'ru', {
sensitivity: 'base' // Игнорировать регистр
})));
Важно знать
Порядок символов в таблице Unicode не совпадает с алфавитным порядком. Например, заглавные буквы идут перед строчными. Всегда используйте localeCompare() для сравнения строк, которые должны учитывать языковые особенности.
Преобразование в строки
Иногда необходимо преобразовать другие типы данных в строку. TypeScript/JavaScriptпредоставляет несколько способов сделать это.
// Способ 1: String()
let число: number = 42;
let строка1: string = String(число);
console.log(строка1); // "42"
// Способ 2: toString()
let строка2: string = число.toString();
console.log(строка2); // "42"
// Способ 3: Шаблонные строки
let строка3: string = `${число}`;
console.log(строка3); // "42"
// Способ 4: Катенация
let строка4: string = "" + число;
console.log(строка4); // "42"
// Преобразование разных типов
console.log(String(true)); // "true"
console.log(String(null)); // "null"
console.log(String(undefined)); // "undefined"
console.log(String([1,2,3])); // "1,2,3"
console.log(String({})); // "[object Object]"
// toString() с основанием системы счисления
let hex: string = (255).toString(16); // "ff"
let bin: string = (10).toString(2); // "1010"
let oct: string = (8).toString(8); // "10"
Практические примеры
Пример 1: Валидация email
function валидироватьEmail(email: string): boolean {
const регулярка = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return регулярка.test(email.trim().toLowerCase());
}
console.log(валидироватьEmail("user@example.com")); // true
console.log(валидertinoEmail("invalid-email")); // false
console.log(валидироватьEmail(" User@Example.COM ")); // true
Пример 2: Капитализация слов
function капитализировать(текст: string): string {
return текст
.toLowerCase()
.split(" ")
.map(слово => слово.charAt(0).toUpperCase() + слово.slice(1))
.join(" ");
}
console.log(капитализировать("привет мир")); // "Привет Мир"
console.log(капитализировать("typescript Language")); // "Typescript Language"
Пример 3: Обрезка текста (truncate)
function обрезатьТекст(
текст: string,
максДлина: number,
суффикс: string = "..."
): string {
if (текст.length <= максДлина) {
return текст;
}
return текст.slice(0, максДлина - суффикс.length) + суффикс;
}
console.log(обрезатьТекст("Длинное название статьи", 15));
// "Длинное назван..."
console.log(обрезатьТекст("Короткий", 20));
// "Короткий"
console.log(обрезатьТекст("Очень длинный текст", 10, "…"));
// "Очень дли…"
Пример 4: Slug для URL
function создатьSlug(заголовок: string): string {
return заголовок
.toLowerCase()
.trim()
.replace(/[^а-яёa-z0-9\s-]/g, "") // Удалить спецсимволы
.replace(/[\s_]+/g, "-") // Заменить пробелы на -
.replace(/-+/g, "-") // Убрать повторяющиеся -
.replace(/^-|-$/g, ""); // Убрать - в начале и конце
}
console.log(создатьSlug("Привет, Мир!")); // "привет-мир"
console.log(создатьSlug("TypeScript 101")); // "typescript-101"
console.log(создатьSlug(" Лучший язык ")); // "лучший-язык"
Частые ошибки
Ошибка 1: Забывают, что строки неизменяемы
let str = "Hello";
str[0] = "h"; // Ошибка! Строки неизменяемы
console.log(str); // "Hello" (не изменилось)
// Правильно: создавать новую строку
let newStr = "h" + str.slice(1); // "hello"
Строки в JavaScript неизменяемы. Любая операция возвращает новую строку.
Ошибка 2: Сравнение строк без учёта регистра
// Неправильно
if (ввод === "admin") { ... } // "Admin" не пройдёт
// Правильно
if (ввод.toLowerCase() === "admin") { ... }
Всегда приводите к единому регистру при сравнении пользовательского ввода.
Ошибка 3: Использование replace() без флага g
// Заменит только первое вхождение
"aaa".replace("a", "b"); // "baa"
// Заменит все вхождения
"aaa".replace(/a/g, "b"); // "bbb"
"aaa".replaceAll("a", "b"); // "bbb"
Используйте replaceAll() или флаг /g для замены всех вхождений.
Подведём итоги
Вы изучили:
- Создание строк:
'', "", `` - Шаблонные строки с интерполяцией
- Методы поиска:
indexOf, includes, search - Методы извлечения:
slice, substring, substr - Методы замены:
replace, replaceAll - Работа с Unicode и эмодзи
Важно помнить:
- Строки неизменяемы (immutable)
- Используйте
localeCompare()для сравнения - Будьте осторожны с эмодзи (длина ≠ количество символов)
- Используйте
padStart/padEndдля форматирования - Всегда обрабатывайте пользовательский ввод
Тест по типу string
10 вопросов