$ sudo teach IT
МОДУЛЬ 2 · УРОК 2

Тип string в TypeScript

Строки, шаблонные строки и методы строк

Добро пожаловать!

Строки — это один из самых важных типов данных в программировании. С их помощью мы работаем с текстом: имена пользователей, сообщения, URL-адреса, сообщения об ошибках — всё это строки. В этом уроке мы детально изучим тип string в TypeScript, научимся создавать строки различными способами, работать с шаблонными строками и использовать богатый набор методов строк.

Цели урока

1
Создавать строки разными способами
2
Использовать шаблонные строки
3
Освоить методы строк
4
Работать с Unicode и эмодзи

Что такое тип 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 вопросов

Форматирование строки

Premium

Обработка строки

Premium