Олег Марков
Заголовок таблицы HTML th - полное руководство
Введение
Элемент <th> в HTML отвечает за заголовки таблиц. С его помощью вы обозначаете, какие ячейки в таблице являются заголовками столбцов или строк, а какие — обычными данными. На первый взгляд это просто "та же ячейка, но жирным", но на самом деле <th> влияет на:
- семантику таблицы;
- поведение экранных читалок (доступность);
- логику сопоставления заголовков и данных;
- стилизацию и восприятие структуры.
Смотрите, я покажу вам, как использовать <th> так, чтобы таблицы были понятными и для людей, и для браузеров, и для вспомогательных технологий.
Основы элемента th
Что такое th и чем он отличается от td
Элемент <th> (table header cell) задает ячейку заголовка в таблице. В отличие от <td>, который представляет обычную ячейку с данными, <th>:
- по умолчанию отображается жирным шрифтом;
- выравнивается по центру по горизонтали (браузерное поведение по умолчанию);
- воспринимается как заголовок для связанных с ним ячеек
<td>; - имеет дополнительные атрибуты для описания своей роли.
Простой пример таблицы с заголовками:
<table>
<tr>
<th>Имя</th> <!-- Заголовок столбца -->
<th>Возраст</th> <!-- Заголовок столбца -->
<th>Город</th> <!-- Заголовок столбца -->
</tr>
<tr>
<td>Анна</td> <!-- Обычная ячейка с данными -->
<td>28</td>
<td>Москва</td>
</tr>
</table>// В первой строке таблицы мы используем th для заголовков столбцов // В следующих строках таблицы применяем td для данных
Как видите, логика простая: <th> — для заголовков, <td> — для данных.
Базовый синтаксис th
Элемент <th> всегда используется внутри строки таблицы <tr> и, соответственно, внутри <table>:
<table>
<tr>
<th>Заголовок 1</th>
<th>Заголовок 2</th>
</tr>
<tr>
<td>Значение 1</td>
<td>Значение 2</td>
</tr>
</table>// Таблица состоит из строк tr // В первой строке используются ячейки th // Во второй строке — ячейки td
Обратите внимание, что <th> и <td> нельзя смешивать внутри одной и той же ячейки, но вы можете использовать их вместе в одной строке, если этого требует структура таблицы.
Расположение заголовков в таблице
Заголовки столбцов (в первой строке)
Чаще всего <th> используют в первой строке таблицы для обозначения заголовков столбцов:
<table>
<tr>
<th>Продукт</th>
<th>Цена</th>
<th>Количество</th>
</tr>
<tr>
<td>Яблоки</td>
<td>120 ₽</td>
<td>10</td>
</tr>
<tr>
<td>Груши</td>
<td>150 ₽</td>
<td>5</td>
</tr>
</table>// th в первой строке задают заголовки столбцов // Каждому столбцу данных соответствует один заголовок th
Это самый распространенный вариант, и именно так большинство пользователей ожидает видеть простые таблицы.
Заголовки строк (в первом столбце)
Иногда логичнее делать заголовками не столбцы, а строки. В этом случае <th> ставится в первом столбце каждой строки данных:
<table>
<tr>
<th>Месяц</th> <!-- Заголовок для первой строки заголовков -->
<th>Доход</th>
<th>Расход</th>
</tr>
<tr>
<th>Январь</th> <!-- Заголовок строки -->
<td>100 000 ₽</td>
<td>80 000 ₽</td>
</tr>
<tr>
<th>Февраль</th> <!-- Заголовок строки -->
<td>120 000 ₽</td>
<td>90 000 ₽</td>
</tr>
</table>// Первый th в первой строке - заголовок столбца "Месяц" // th в следующих строках - заголовки соответствующих строк
Здесь <th> в первой строке задает заголовки столбцов, а <th> в первом столбце — заголовки строк. Такое смешанное использование допустимо и полезно.
Комбинация заголовков строк и столбцов
Давайте разберем пример, когда у нас и шапка таблицы, и подписи строк:
<table>
<tr>
<th></th> <!-- Пустая ячейка в левом верхнем углу -->
<th>Понедельник</th>
<th>Вторник</th>
<th>Среда</th>
</tr>
<tr>
<th>Утро</th> <!-- Заголовок строки -->
<td>Совещание</td>
<td>Разработка</td>
<td>Поддержка</td>
</tr>
<tr>
<th>День</th> <!-- Заголовок строки -->
<td>Код ревью</td>
<td>Разработка</td>
<td>Обучение</td>
</tr>
</table>// В первой строке задаем заголовки столбцов дня недели // В первом столбце задаем заголовки строк времени суток
Такая структура делает таблицу более читаемой и помогает пользователю быстро сопоставлять данные с контекстом.
Атрибут scope — связь заголовков и данных
Зачем нужен scope
Атрибут scope у <th> помогает явно указать, к каким ячейкам относится данный заголовок. Это важно:
- для экранных читалок (чтобы правильно озвучивать данные);
- для сложных таблиц с несколькими уровнями заголовков;
- для таблиц, где заголовки расположены не только сверху, но и сбоку.
scope может принимать следующие значения:
col— заголовок столбца;row— заголовок строки;colgroup— заголовок группы столбцов;rowgroup— заголовок группы строк.
Примеры использования scope="col" и scope="row"
Давайте посмотрим простой, но правильный с точки зрения семантики пример:
<table>
<tr>
<th scope="col">Имя</th> <!-- Заголовок столбца -->
<th scope="col">Возраст</th>
<th scope="col">Город</th>
</tr>
<tr>
<th scope="row">Анна</th> <!-- Заголовок строки -->
<td>28</td>
<td>Москва</td>
</tr>
<tr>
<th scope="row">Иван</th> <!-- Заголовок строки -->
<td>35</td>
<td>Санкт-Петербург</td>
</tr>
</table>// scope="col" сообщает что th является заголовком столбца // scope="row" сообщает что th является заголовком всей строки
Экранная читалка при озвучивании ячейки с возрастом сможет сообщить и имя человека, и название столбца, что делает таблицу более понятной.
scope для групп — colgroup и rowgroup
Значения colgroup и rowgroup используются реже и в основном в сложных таблицах с логически объединенными строками или столбцами.
Пример, чтобы вам было проще понять:
<table>
<tr>
<th></th>
<th scope="colgroup" colspan="2">Продажи</th> <!-- Группа столбцов -->
<th scope="colgroup" colspan="2">Расходы</th> <!-- Группа столбцов -->
</tr>
<tr>
<th></th>
<th scope="col">План</th>
<th scope="col">Факт</th>
<th scope="col">План</th>
<th scope="col">Факт</th>
</tr>
<tr>
<th scope="row">Январь</th>
<td>100 000</td>
<td>95 000</td>
<td>60 000</td>
<td>58 000</td>
</tr>
</table>// Первый ряд верхних th с scope="colgroup" описывает сразу по два столбца // Второй ряд th с scope="col" уточняет каждый отдельный столбец
Так таблица становится понятнее логически — есть группы "Продажи" и "Расходы" с подзаголовками.
Атрибуты colspan и rowspan у th
Расширение заголовков по горизонтали — colspan
colspan определяет, на сколько столбцов должна растянуться ячейка <th>. Это удобно, когда один заголовок относится сразу к нескольким соседним столбцам.
<table>
<tr>
<th>Квартал</th>
<th colspan="3">Продажи по месяцам</th> <!-- Один заголовок на 3 столбца -->
</tr>
<tr>
<th></th>
<th>Январь</th>
<th>Февраль</th>
<th>Март</th>
</tr>
<tr>
<th>I квартал</th>
<td>100 000</td>
<td>120 000</td>
<td>110 000</td>
</tr>
</table>// colspan="3" растягивает th на три столбца // Визуально создается заголовок группы подмесяцев
Важно, чтобы значение colspan соответствовало реальному количеству ячеек в строке, иначе структура таблицы "поедет".
Расширение заголовков по вертикали — rowspan
rowspan определяет, на сколько строк растягивается ячейка <th>. Это полезно, когда один заголовок относится к нескольким строкам:
<table>
<tr>
<th rowspan="2">Категория</th> <!-- Заголовок для двух строк -->
<th>Товар</th>
<th>Цена</th>
</tr>
<tr>
<th>Доп. информация</th>
<th>Склад</th>
</tr>
<tr>
<th rowspan="2">Фрукты</th>
<td>Яблоки</td>
<td>120 ₽</td>
</tr>
<tr>
<td>Импортные</td>
<td>Склад 3</td>
</tr>
</table>// rowspan="2" растягивает th по вертикали на две строки // Это позволяет показывать что обе строки относятся к одной категории
Когда вы комбинируете rowspan и colspan, следите, чтобы структура строки и столбцов оставалась согласованной. Если что-то "не сходится", браузеры начнут перераспределять ячейки автоматически, и отладка может стать неприятной.
Взаимодействие th с thead, tbody и tfoot
Логическое разделение таблицы
Элемент <th> можно и нужно использовать внутри thead, tbody и tfoot. Эти элементы помогают логически разделить таблицу:
thead— шапка таблицы;tbody— основное содержимое;tfoot— подвал (итоги, примечания).
Пример:
<table>
<thead>
<tr>
<th>Товар</th>
<th>Цена</th>
<th>Количество</th>
</tr>
</thead>
<tbody>
<tr>
<td>Яблоки</td>
<td>120 ₽</td>
<td>10</td>
</tr>
<tr>
<td>Груши</td>
<td>150 ₽</td>
<td>5</td>
</tr>
</tbody>
<tfoot>
<tr>
<th>Итого</th>
<td>270 ₽</td>
<td>15</td>
</tr>
</tfoot>
</table>// thead содержит заголовки столбцов в th // tbody содержит обычные данные в td // tfoot может содержать итоговые значения и заголовки
<th> внутри tfoot по-прежнему остается заголовком, просто логически находящимся в нижней части таблицы.
Зачем это нужно на практике
- Браузеры могут "прилиплять"
theadпри прокрутке (если используются соответствующие стили или JS-плагины). - Экранные читалки лучше понимают структуру.
- Код таблицы становится понятнее, когда вы его поддерживаете или изменяете.
Стилизация th с помощью CSS
Базовая стилизация th
По умолчанию <th> выглядит жирным и выравнивается по центру. Но вы почти всегда захотите настроить это под свой дизайн.
Давайте посмотрим простой пример:
<style>
th {
font-weight: 600; /* Чуть менее жирный шрифт */
text-align: left; /* Выравниваем заголовки по левому краю */
background-color: #f5f5f5; /* Светлый фон для заголовков */
padding: 8px 12px; /* Внутренние отступы */
}
td {
padding: 8px 12px; /* Те же отступы для данных */
}
</style>// Мы переопределяем стандартный стиль th // Стараемся сделать заголовки визуально отличимыми но не кричащими
Вы можете определить отдельные стили для заголовков столбцов и строк:
thead th {
background-color: #e0f0ff; /* Заголовки в шапке таблицы */
}
tbody th {
background-color: #f0ffe0; /* Заголовки строк */
}// thead th стилизует только th внутри шапки таблицы // tbody th стилизует заголовки строк в теле таблицы
Фиксированная шапка таблицы (при прокрутке)
Одна из частых задач — сделать так, чтобы заголовки таблицы оставались на виду при вертикальной прокрутке. Здесь <th> играет ключевую роль, а дальше подключается CSS.
Пример:
<style>
table {
border-collapse: collapse; /* Убираем двойные границы */
width: 100%;
}
thead th {
position: sticky; /* Прилипание заголовков */
top: 0; /* Позиция относительно верхней границы контейнера */
background: #fff; /* Фон чтобы текст не сливался с данными */
z-index: 2; /* Поверх содержимого */
}
th, td {
border: 1px solid #ccc; /* Простая граница между ячейками */
padding: 8px;
}
.table-wrapper {
max-height: 200px; /* Ограничиваем высоту */
overflow-y: auto; /* Добавляем вертикальную прокрутку */
}
</style>
<div class="table-wrapper">
<table>
<thead>
<tr>
<th>Имя</th>
<th>Возраст</th>
<th>Город</th>
</tr>
</thead>
<tbody>
<!-- Здесь располагаются строки с данными -->
</tbody>
</table>
</div>// position: sticky работает только внутри прокручиваемого контейнера // Поэтому мы оборачиваем таблицу в div с overflow-y: auto
Теперь вы увидите, что шапка таблицы остается наверху при прокрутке.
Состояния и ховеры для заголовков
Иногда полезно подсвечивать столбец при наведении на его заголовок (например, при сортировке). Полноценное подсвечивание всех ячеек столбца потребует JS, но базовые эффекты можно задать сразу:
th.sortable {
cursor: pointer; /* Показываем что заголовок интерактивен */
}
th.sortable:hover {
background-color: #e8f2ff; /* Подсветка при наведении */
}// Класс sortable используется для кликабельных заголовков // При наведении меняем цвет фона чтобы показать интерактивность
Техническую реализацию сортировки вы можете добавить на JS, а <th> здесь просто визуальная и семантическая опора.
Семантика и доступность th
Почему важно использовать th правильно
Когда вы используете <th> вместо <td> для заголовков, вы:
- помогаете экранным читалкам правильно связать данные с заголовками;
- улучшаете навигацию по таблице для пользователей с ограничениями по зрению;
- делаете структуру таблицы понятнее для автоматических инструментов анализа.
Если вы стилизуете <td> так, что он выглядит как заголовок, но не используете <th>, то визуально для большинства все будет нормально, но доступность сильно пострадает.
Пример корректной таблицы с точки зрения доступности
Давайте посмотрим на расширенный пример:
<table>
<caption>Расписание занятий группы А-101</caption> <!-- Описание таблицы -->
<thead>
<tr>
<th scope="col">День</th>
<th scope="col">Время</th>
<th scope="col">Предмет</th>
<th scope="col">Аудитория</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Понедельник</th>
<td>9:00 - 10:30</td>
<td>Математика</td>
<td>101</td>
</tr>
<tr>
<th scope="row">Вторник</th>
<td>11:00 - 12:30</td>
<td>Физика</td>
<td>203</td>
</tr>
</tbody>
</table>// caption описывает назначение таблицы // th с scope="col" задают заголовки столбцов // th с scope="row" задают заголовки строк "День"
Экранная читалка, озвучивая, например, ячейку "Физика", сможет сообщить: "Вторник, 11:00 - 12:30, Физика", что улучшает ориентацию пользователя.
Когда нужны атрибуты headers и id
В очень сложных таблицах одного scope может быть недостаточно. Тогда применяют id на <th> и атрибут headers на <td>, чтобы явно указать, какие заголовки относятся к ячейке.
Пример, чтобы вы увидели, как это выглядит в коде:
<table>
<tr>
<th id="month">Месяц</th>
<th id="sales">Продажи</th>
<th id="expenses">Расходы</th>
</tr>
<tr>
<td headers="month">Январь</td>
<td headers="sales">100 000</td>
<td headers="expenses">60 000</td>
</tr>
</table>// id на th задает уникальный идентификатор заголовка // headers на td ссылается на id заголовка к которому относится ячейка
Для простых таблиц это избыточно, но для сильно вложенных и комплексных структур может быть единственным корректным решением.
Типичные ошибки при использовании th
Использование td вместо th для заголовков
Очень частая ситуация — когда разработчик делает шапку таблицы на <td>, просто применяя к ним жирный шрифт.
<!-- Пример неудачного подхода -->
<tr>
<td><b>Имя</b></td>
<td><b>Возраст</b></td>
</tr>// Визуально выглядит как заголовок но семантика таблицы нарушена // Экранные читалки не поймут что это заголовки
Правильнее заменить <td> на <th> и задать стили через CSS вместо <b>.
Злоупотребление th в ячейках данных
И обратная крайность — использовать <th> для "важных" ячеек с данными, которые не являются заголовками.
<!-- Пример неправильного использования -->
<tr>
<th>Скидка 50%</th> <!-- Это не заголовок столбца или строки -->
<td>Только сегодня</td>
</tr>// Хотя ячейка важная по смыслу она не является заголовком набора данных // Нужно использовать td с более заметным стилем а не th
Семантика важнее "важности" текста. Если это не заголовок для строки или столбца — используйте <td>.
Отсутствие scope в сложных таблицах
В простых таблицах браузер может автоматически сопоставлять <th> и <td>. Но как только структура становится сложнее (несколько уровней заголовков, объединенные ячейки), отсутствие scope начинает мешать доступности.
Хорошее правило: если у вас есть более одного ряда заголовков или вы используете rowspan/colspan для <th>, стоит явно указать scope.
Неправильное сочетание rowspan и colspan
Ошибки в значениях rowspan и colspan ведут к "ломанию" таблицы. Например, если в одной строке суммарное количество ячеек (с учетом растяжения) отличается от других строк, браузер будет пытаться исправить разметку, и результат часто оказывается неожиданным.
Чтобы этого избежать:
- прорисуйте структуру таблицы на бумаге или в виде сетки;
- посчитайте, чтобы итоговое число столбцов (с учетом
colspan) совпадало во всех строках; - проверьте, чтобы
rowspanне перекрывал лишние строки.
Практические примеры использования th
Пример 1 — Простая табличная отчетность
Давайте рассмотрим обычную таблицу отчета по продажам:
<table>
<caption>Отчет по продажам за 2024 год</caption>
<thead>
<tr>
<th scope="col">Месяц</th>
<th scope="col">Продажи</th>
<th scope="col">Расходы</th>
<th scope="col">Прибыль</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Январь</th>
<td>100 000</td>
<td>60 000</td>
<td>40 000</td>
</tr>
<tr>
<th scope="row">Февраль</th>
<td>120 000</td>
<td>70 000</td>
<td>50 000</td>
</tr>
</tbody>
</table>// Используем caption для названия отчета // th с scope="col" и scope="row" обеспечивают понятную структуру данных
Такой подход к <th> делает отчет более ясным для всех типов пользователей.
Пример 2 — Матрица с заголовками по строкам и столбцам
Представим таблицу сравнения тарифов:
<table>
<caption>Сравнение тарифов</caption>
<thead>
<tr>
<th></th>
<th scope="col">Базовый</th>
<th scope="col">Стандарт</th>
<th scope="col">Премиум</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Цена в месяц</th>
<td>500 ₽</td>
<td>900 ₽</td>
<td>1500 ₽</td>
</tr>
<tr>
<th scope="row">Объем хранилища</th>
<td>10 ГБ</td>
<td>50 ГБ</td>
<td>200 ГБ</td>
</tr>
<tr>
<th scope="row">Поддержка 24/7</th>
<td>Нет</td>
<td>Да</td>
<td>Да</td>
</tr>
</tbody>
</table>// Пустой th в левом верхнем углу нужен чтобы сетка выглядела аккуратно // Заголовки строк описывают характеристики // Заголовки столбцов описывают тарифы
Здесь <th> по обеим осям (строки и столбцы) делает структуру очевидной.
Пример 3 — Сложная таблица с объединенными заголовками
Покажу вам пример с несколькими уровнями заголовков и объединением ячеек:
<table>
<caption>Статистика посещений сайта</caption>
<thead>
<tr>
<th rowspan="2" scope="col">Страница</th>
<th colspan="2" scope="colgroup">Десктоп</th>
<th colspan="2" scope="colgroup">Мобайл</th>
</tr>
<tr>
<th scope="col">Просмотры</th>
<th scope="col">Уники</th>
<th scope="col">Просмотры</th>
<th scope="col">Уники</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Главная</th>
<td>10 000</td>
<td>7 000</td>
<td>8 000</td>
<td>5 500</td>
</tr>
<tr>
<th scope="row">Каталог</th>
<td>6 000</td>
<td>4 000</td>
<td>5 000</td>
<td>3 500</td>
</tr>
</tbody>
</table>// Первый ряд th задает большие группы десктоп и мобайл // Второй ряд th уточняет какие именно метрики внутри каждой группы // rowspan="2" для th "Страница" связывает его с двумя рядами заголовков справа
Здесь использование scope="colgroup" помогает экраночиталкам понять логическую группировку столбцов.
Пример 4 — Адаптивная таблица с акцентом на заголовки строк
В мобильной вёрстке иногда проще "перевернуть" акцент: заголовки строк становятся более важными.
Один из подходов — при узком экране превращать таблицу в карточки, но в исходной разметке одновременно сохранить <th> как заголовки строк:
<table class="pricing-table">
<caption>Тарифы для бизнеса</caption>
<thead>
<tr>
<th scope="col">Параметр</th>
<th scope="col">Малый бизнес</th>
<th scope="col">Корпорация</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Цена в месяц</th>
<td>2000 ₽</td>
<td>8000 ₽</td>
</tr>
<tr>
<th scope="row">Количество аккаунтов</th>
<td>10</td>
<td>Неограниченно</td>
</tr>
<tr>
<th scope="row">Лимит проектов</th>
<td>50</td>
<td>Неограниченно</td>
</tr>
</tbody>
</table>// th в первой колонке задают "параметры" тарифа // При адаптивной стилизации эти заголовки легко использовать как подписи в карточках
CSS здесь уже сделает остальную работу, но именно <th> дает "якорь" для понимания структуры.
Заключение
Элемент <th> в HTML — это не просто "жирная ячейка" в таблице. Он задает семантику заголовков, помогает связать данные с контекстом, влияет на доступность и улучшает читаемость. Корректное использование <th> вместе с атрибутами scope, rowspan, colspan, а при необходимости — id и headers, делает даже сложные таблицы понятными.
Основные практические выводы:
- используйте
<th>для заголовков столбцов и строк, а<td>— для данных; - в сложных таблицах явно указывайте
scope; - комбинируйте
<th>сthead,tbody,tfootдля логичной структуры; - не злоупотребляйте
<th>в ячейках, которые не являются заголовками; - учитывайте доступность и работу экранных читалок.
Если вы при проектировании таблицы сначала думаете о структуре и связи "заголовок → данные", а уже потом о визуальном оформлении, <th> становится естественным и мощным инструментом, а не просто декоративным элементом.
Частозадаваемые технические вопросы по теме
1. Как сделать так чтобы при клике по заголовку th сортировались данные в столбце
Один из простых подходов — добавить обработчик клика на <th> и при клике сортировать массив данных, а затем перерисовывать <tbody>.
Пошагово:
- Назначьте класс, например
class="sortable"на заголовки, по которым хотите сортировать. - В JS выберите все такие
<th>и повесьте на них обработчикclick. - В обработчике:
- определить индекс столбца;
- получить все строки
<tbody>; - отсортировать их по значению в соответствующей ячейке
<td>; - заменить содержимое
<tbody>на отсортированный набор.
Важно: храните текущий порядок сортировки (по возрастанию/убыванию) и меняйте его при каждом клике.
2. Можно ли сделать многострочный заголовок в одной ячейке th
Да. Используйте перенос строки через <br> или блочные элементы:
<th>Продажи<br>за квартал</th>или
<th>
<span>Продажи</span>
<span>за квартал</span>
</th>Второй вариант удобнее стилизовать через CSS. Следите, чтобы текст оставался читаемым на маленьких экранах.
3. Как задать разную ширину столбцов с th
Есть несколько вариантов:
- использовать CSS-свойство
widthнаthили на столбцах через<colgroup>; - добавить класс к нужному
<th>и задатьwidthв процентах или пикселях; - при необходимости использовать
table-layout: fixedдля более предсказуемого поведения.
Пример:
<style>
th.col-name { width: 40%; }
th.col-age { width: 10%; }
</style>Применяйте классы к соответствующим заголовкам.
4. Что делать если th отображается по центру а мне нужно выравнивание по левому краю во всех таблицах
По умолчанию <th> центрирует текст, поэтому задайте глобальный стиль:
th {
text-align: left;
}Если где-то нужно иное выравнивание, используйте дополнительные классы:
th.center {
text-align: center;
}И назначайте class="center" только тем заголовкам, где это требуется.
5. Как скрыть заголовки th визуально но оставить их доступными для экранных читалок
Используйте технику "visually hidden":
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
border: 0;
}И применяйте класс к <th>:
<th class="visually-hidden" scope="col">Технический заголовок</th>Так заголовок будет недоступен визуально, но останется в DOM и будет читаться экранными читалками.
Постройте личный план изучения Html до уровня Middle — бесплатно!
Html — часть карты развития Frontend
100+ шагов развития
30 бесплатных лекций
300 бонусных рублей на счет
Все гайды по Html
Лучшие курсы по теме

HTML и CSS
Антон Ларичев
TypeScript с нуля
Антон Ларичев