Практический TypeScript

Оглавление⌄
Оглавление....2 📖 Быстрая навигация по разделам....2 🏗️ Основы TypeScript....2 🔧 Система типов....2 📝 Лучшие практики....3 🚀 Продвинутые типы....4 📦 Публикация и API....5 ⚡ Производительность и миграция....5 📚 Справочные материалы....6 💡 Как использовать навигацию....6 Предисловие....6 Материалы охватывают основные темы TypeScript:....7 Для кого эта книга....7 Как использовать....7 Введение....7 Контакты....7 🏗️ Основы TypeScript (01-10)....9 Как TypeScript связан с JavaScript....9 🔷 Что такое JavaScript?....9 🔷 Что такое TypeScript?....9 🔁 Связь между TypeScript и JavaScript:....9 🔨 Как TypeScript работает?....10 📦 Как представить TypeScript?....10 Представь, что:....10 🧠 Важно запомнить:....10 Как Выбирать нужные опции в TypeScript....10 📁 Где вообще настраивается TypeScript?....11 🧭 Как выбирать нужные опции?....11 ✅ 1. `strict: true` — строгий режим....11 🔍 2. `noImplicitAny: true` — запрет на неявный `any`....11 🔐 3. `strictNullChecks: true` — не смешивать `null` и другиетипы....11 🎯 4. `target: "ES6"` (или выше)....12 📦 5. `module: "commonjs"` или `"ESNext"`....12 📂 6. `rootDir` и `outDir`....12 📘 Другие полезные:....12 🚀 Советы по выбору:....12 🔧 Минимальный рекомендуемый `tsconfig.json`:....13 Генерация кода не зависит от типов....13 📌 Что это значит?....13 🧠 То есть: **типы — это как инструкция для разработчика икомпилятора**, но не для машины.....13 📦 Пример:....13 🧪 Почему это важно?....14 🧯 Что будет, если ты ошибся?....14 🧰 Если нужна проверка типа в рантайме....14 ✨ Итог:....15 Что такое структурная типизация?....15 🧱 Что такое **структурная типизация**?....15 📦 Пример:....15 📛 В других языках (например, Java, C#) — **номинативнаятипизация**....16 🎯 Главное правило структурной типизации:....16 ❗️ Из этого следуют плюсы и минусы:....16 ✅ Плюсы:....16 ❌ Минусы:....16 📌 Пример из жизни:....17 ✨ Вывод:....17 Как ограничить тип any....17 📌 Почему `any` опасен?....17 ✅ Способы ограничить или запретить `any`....18 1. **Включи строгий режим**....18 2. **`noImplicitAny: true`** — запрет неявного `any`....18 3. **`strictFunctionTypes: true`**....18 4. **Запретить `any` полностью — через линтер**....19 5. **Заменять `any` на более безопасные альтернативы**....19 `unknown` — безопасная альтернатива:....19 ✨ Дополнительно:....19 🔚 Вывод:....20 Как использовать редактор дляполучения информации о системе типов....20 🛠 1. **Наведи мышку на переменную, функцию,тип**....20 💡 2. **Cmd (Mac) / Ctrl (Win) + Click** — перейти копределению....21 🔍 3. **F12** или **"Go to Definition"**....21 ⌨️ 4. **TypeScript: Go to Type Definition**....21 💬 5. **Типовые подсказки при наведении**....21 🔁 6. **Проверка типа через `as const`, `typeof`,`satisfies`**....22 💥 7. **Проверка вывода типа: `type T = typeof x`**....22 🧪 Бонус: **Inline Type Explorer** (только вредакторе)....22 🧰 Что тебе нужно?....22 🔚 Итог: как изучать типы через редактор....23 Типы как множества значений....23 🧠 Идея: **тип = множество возможных значений**....23 📦 Примеры:....23 🔢 Примитивные типы....23 🧮 Объединения (Union) = объединение множеств....24 🚫 Пересечения (Intersection) = пересечение множеств....24 📜 Литеральные типы = конкретные значения....24 📐 Подтипы и расширение....24 🤔 Зачем это понимать?....25 🧪 Пример с проверкой:....25 ✅ Вывод:....25 Как выражать принадлежностьсущностей к пространству типов илипространству значений....26 📌 Главное различие:....26 ✅ Пространство **типов**:....26 ✅ Пространство **значений**:....26 🚦 Как выразить принадлежность?....27 1. **К типам** — через `:` или `extends`....27 2. **К значениям** — через `typeof`, `instanceof`, `typeof x ==="..."`....27 🎯 Как не путать?....27 💡 Мнемоника:....28 🧪 Пример из жизни:....28 🧠 Advanced: только в пространстве типов....28 ✅ Вывод....28 Как отдавать предпочтение аннотациямтипов, а не утверждениям....29 ✅ **Аннотация типов (type annotation)** —правильно....29 ⚠️ **Утверждение типов (type assertion)** —потенциально опасно....29 📌 Главное отличие:....30 🧠 Почему отдаём предпочтение **аннотациям**?....30 ✅ 1. **Аннотации проверяются**....30 ⚠️ А утверждение может обмануть:....30 ✅ 2. **Аннотация документирует намерения**....30 ✅ 3. **Работает с type inference**....30 🤯 Почему утверждения (`as`) — это костыль?....31 📎 Когда **можно использовать утверждение(`as`)**?....31 🔚 Вывод....31 Как и для чего избегать объектных типов-оберток (String, Number, Boolean, Symbol,BigInt)....31 🧱 1. Что такое "объектные обёртки"?....32 🚫 Почему **НЕ нужно использовать** обёртки?....32 ⚠️ 1. Это не одно и то же!....32 ⚠️ 2. Обёртки ломают строгую типизацию....32 ⚠️ 3. Могут привести к странным багам....33 ✅ Что использовать вместо них?....33 ✅ Как писать правильно в TypeScript:....33 📌 Исключение: типы `Object`, `Function` и `{}`....34 🔍 Пример ошибки:....34 ✅ Вывод....34 🔧 Система типов (11-30)....35 Проверка лишних свойств....35 📌 Главное различие:....35 🔍 Пример — **типовая проверка** (всё нормально)....35 🛑 Пример — **проверка лишних свойств**....35 📌 Правило:....36 ✅ Как обойти (если нужно):....36 1. Вынести в переменную....36 2. Использовать оператор утверждения:....36 3. Указать "дополнительные свойства" в типе:....36 🧠 Почему TypeScript так делает?....36 🧪 Мини-сводка:....37 🧩 Вывод:....37 Как задать тип всему функциональномувыражению....37 ✅ Цель: **типизировать всю функцию целиком**,а не только параметры или `return`.....37 🧠 Способы применять типы ко всемуфункциональному выражению:....38 ✅ 1. **Через аннотацию переменной**....38 ✅ 2. **Через `type` или `interface`**....38 ✅ 3. **Анонимные функции с аннотацией**....38 ✅ 4. **Стрелочная функция в типе функции высшего порядка**....38 ⚠️ Антипаттерн: тип только у параметров....39 ✍️ Советы:....39 ✅ Пример: полная типизация....39 Различия между type и interface....40 🔹 Оба `interface` и `type` делают почти одно и тоже:....40 🔑 Но в чём же разница?....40 1. **Расширение (наследование)**....40 ✅ `interface` легко **дополняется и объединяется**....40 ⛔️ `type` так **не умеет**....41 2. **Композиция (соединение)**....41 `type` — мощнее в комбинировании....41 3. **Классы**....41 4. **Типы не только объектов**....41 🧠 Как запомнить:....42 Readonly в TypeScript....42 🔒 Что делает `readonly`?....42 🧱 Пример: `readonly` в объектах....42 🧩 Пример: `readonly` для массивов....43 🧰 Где `readonly` особенно полезен....43 ✅ 1. Константные данные....43 ✅ 2. Передача аргументов в функции....43 ✅ 3. В Redux, Zustand и других хранилищах....44 🔁 Readonly утилиты....44 ✋ Почему это важно?....44 🧠 Вывод....45 Сравнение с `const` и `Object.freeze()`....45 📚 Кратко: как они работают....45 🔍 Подробнее:....45 ✅ 1. `const`....45 ✅ 2. `readonly` (TS)....46 ✅ 3. `Object.freeze()` (JS)....46 🔁 Как их сочетать....46 ✅ Самое безопасное — вместе:....46 ❗️ В чём подвох?....47 1. `readonly` — **не работает во время выполнения**....47 2. `Object.freeze()` — **не гарантирует типовую защиту**....47 📌 Итоговая таблица сравнения....47 💡 Рекомендация....47 Как использовать операции типов....48 🔧 Что такое операции над типами?....48 📦 Пример: избежать повторов с `Pick`....48 🧹 Пример: `Omit` для исключения....49 🧩 Пример: `Partial` и `Required`....49 📘 Обобщения (дженерики) для повторногоиспользования....49 🛠 Комбинирование: обобщения + операции надтипами....50 📌 Вывод....50 🎓 Пример для вдохновения....50 Используйте более точные альтернативыдля сигнатур индексов....51 🚫 Проблема с «широкой» индексной сигнатурой....51 ✅ Альтернатива 1: Перечисление известныхключей....51 ✅ Альтернатива 2: Использовать `Record`....52 ✅ Альтернатива 3: Использовать объект сшаблонными ключами....52 ✅ Альтернатива 4: Типы через Map/Set....52 ⚖️ Сравнение подходов....52 📌 Вывод....53 Избегайте использования числовыхсигнатур индексов....53 🧱 Что такое числовая сигнатура индекса?....54 ❌ Почему **не стоит** использовать `[index:number]`?....54 ✅ Альтернатива 1: Использовать `string[]` или`Array`....54 ✅ Альтернатива 2: Кортежи — для фиксированнойдлины....54 ✅ Альтернатива 3: Объекты с ключами-числами(если нужны)....55 🧠 Совет: если нужна структура**массивоподобная**, используй массив (`Array`), ане `[index: number]: T`....55 📌 Итого....55 Не засорять код лишними аннотациямитипов....55 🧠 Правило: **Аннотируй там, где это нужно**, а невезде....56 ✅ Где **не нужно** писать аннотацию — TypeScript самсправится:....56 Присваивание переменной....56 Возвращаемое значение из `map`, `filter`, `reduce` и т.п.....56 Функции с очевидным типом возвращаемого значения....56 ✅ Где **стоит** писать аннотации....56 ❌ Пример кода с лишними аннотациями (плохо)....57 📌 Совет....58 Используйте разные переменные дляразных типов....58 📌 В чём идея?....58 ❌ Плохой пример — всё в одной переменной....58 ✅ Хороший пример — отдельные переменные....59 💡 Где это особенно важно?....59 1. **Обработка разных данных**....59 2. **Работа с результатами API**....59 🚫 Почему не стоит делать так:....60 📋 Резюме....60 Что такое расширение типов в TypeScript....60 🧱 Что такое "расширение типов"?....61 ✅ Пример: расширяем `User`....61 🧰 Два способа расширять типы....61 1. Через `extends` в интерфейсах....61 2. Через `&` (intersections) в `type`....62 🔄 Расширение с изменением типа....62 📐 Когда это нужно?....62 🧠 Важно помнить....62 📌 Резюме....63 Почему лучше создавать объектыцеликом....63 🧩 Что значит "создавать объект целиком"?....63 ❌ Плохо — создаём объект по частям....63 🚨 Почему это плохо:....63 ✅ Хорошо — создать объект сразу целиком....64 👍 Почему это хорошо:....64 🧠 Зачем это правило?....64 🛡️ А что если объект создаётся динамически?....64 💡 Совет: Не используй `as Type` для "достройки"объекта....64 ✅ Можно использовать вспомогательные функции....65 🧪 Проверка лишних свойств тоже работает толькопри **целиком созданном объекте**....65 📌 Вывод....65 Сужение типов....66 📌 Что такое сужение типов?....66 📦 Пример: объединённый тип....66 🔧 Способы сужения типов....66 1. **`typeof` — для примитивов**....66 2. **`in` — для объектов с разными полями**....67 3. **Сравнение с `null`, `undefined`**....67 4. **`===` / `!==` — для литералов**....67 5. **Проверка через пользовательский `type guard`**....67 ⚠️ Без сужения — плохо....68 🧠 Как освоить:....68 ✅ Сужение = без `any`, без кастов (`as`), безошибок....68 Как быть последовательным сиспользованием псевдонимов....68 🧾 Что такое псевдонимы типов?....69 ✅ Как быть последовательным — простыеправила....69 1. **Если начал использовать псевдонимы — используй ихвезде**....69 2. **Даём имена, отражающие смысл**....69 3. **Избегаем избыточности**....70 4. **Отделяй alias от интерфейсов**....70 5. **Пиши в одном стиле: либо `type`, либо `interface`, немешай без причины**....70 6. **Разделяй области: отдельные файлы/модули для типов**....71 📌 Резюме: как быть последовательным....71 Как использовать контекст при выводетипов....71 🧠 Что такое контекстный вывод типов?....71 📦 Примеры....72 ✅ Пример 1. Callback в `.map`....72 ✅ Пример 2. Обработчик события....72 ✅ Пример 3. Функции как параметры....72 🚫 Пример, где контекста нет → нужен явный тип....72 🧠 Где работает контекстный вывод:....73 💡 Советы: как эффективно использовать....73 ✅ Используй функции в контексте....73 ✅ Не пиши типы, если контекст их даёт....73 ❗️ Не полагайся на вывод, если:....74 📌 Резюме....74 Эволюционирующие типы....74 🧠 Что такое *эволюционирующий тип*?....74 🔍 Пример:....74 🧩 Другой пример: массив....75 ❗️Почему это опасно?....75 ✅ Как правильно:....75 1. **Сразу задавай явный тип**....75 2. **Используй `const` вместо `let`, если значение неизменяется**....75 3. **Для массивов указывай тип, даже если он пустой**....76 4. **Не полагайся на `let x;` без типа**....76 🔄 Типичная ловушка....76 📌 Резюме....76 Функциональные конструкции ибиблиотеки для улучшения работы стипами....77 🧠 Идея: типы и функции должны быть *связаны*....77 ✅ Что значит "функциональные конструкции"?....77 📦 Примеры и как они улучшают типы....77 1. **Функции высшего порядка с типами**....77 2. **Функции-комбинаторы (`pipe`, `compose`)**....78 3. **Типизированные контейнеры: `Option`, `Either`**....78 4. **Pattern Matching (например, `ts-pattern`)**....78 📚 Полезные библиотеки....79 🎯 Как улучшает работу с типами?....79 💡 Советы....79 Async-функции вместо обратных вызовов....79 🔁 Что такое "обратный вызов" (callback)?....80 ✅ Как использовать `async/await` вместо этого....80 🧠 Как это улучшает работу с типами....80 🧱 Как переделать код с callback → `async`....81 Было:....81 Стало:....81 🧯 Обработка ошибок....81 📌 Резюме....82 📚 Советы....82 Классы и каррирование для созданияновых точек вывода типов....82 🔎 Что такое "точка вывода типов"?....82 🧱 1. Классы как точка вывода....83 🔄 2. Каррирование как точка вывода....83 🔁 Пример: создать трансформатор с классом икаррированием....84 ⚡️ Комбинация: каррированная функция-конструктор с классом....84 🧠 Зачем это нужно?....84 📌 Резюме....85 Моделирование допустимых состояний(valid states)....85 🧠 Цель:....85 ✅ Принципы:....85 🔧 Пример: загрузка данных....85 ❌ Неправильно (можно совместить несовместимое):....85 ✅ Правильно (моделируем допустимые состояния явно):....86 🧱 Пример: формы....86 📌 Техника: \[**Tagged unions** / Discriminatedunions\*\*]....87 ✨ Плюсы подхода....87 ❗️ Не допускай таких состояний:....87 🧠 Подсказка: типы = множества допустимыхзначений....88 🔚 Резюме....88 Будь консервативным в отправке,либеральным в приёме....88 📌 Принцип:....88 🔧 На практике в TypeScript:....88 1. **Либеральный приём: принимать больше вариантов**....88 2. **Консервативная передача: возвращать минимальнодостаточное**....89 💡 Почему это важно?....89 ✅ Пример хорошего баланса....89 🛑 Что не делать....90 ❌ Не возвращай «тяжёлые» объекты:....90 🧠 Пример с типами:....90 📌 Итоговое правило:....90 📝 Лучшие практики (31-49)....91 Не повторять информацию типа вдокументации....91 🎯 Принцип....91 ❌ Пример плохой практики....91 ✅ Лучше так:....91 🔧 Когда писать документацию?....92 📌 Правило: "Объясняй поведение, не структуру"....92 🤖 Вместо комментариев — используйте мощныетипы....92 ✨ Используй JSDoc там, где это нужно:....93 🧠 Вывод....93 Избегать включения null или undefined впсевдонимы типов....93 🔎 Что это значит?....93 ❌ Почему это плохо?....93 ✅ Что делать вместо этого....94 1. Разделяй "есть значение" и "нет значения"....94 2. Избегай включения `null | undefined` в сам тип....94 3. Будь явным в том, что `null` или `undefined` — часть логики....95 🧠 Пример из жизни....95 🔧 Резюме: как избегать `null` / `undefined` впсевдонимах....95 Вынесение null на периферию типов....95 🔎 Что значит "на периферию"?....96 📉 ❌ Плохо: `null`/`undefined` внутри сложныхтипов....96 📈 ✅ Хорошо: оборачивай всё в явно различимыеформы....96 📌 Подход: моделируй отсутствие целиком, а некусками....97 📌 "Периферия" — это:....97 🔧 Примеры на практике....97 ❌ Внутри структуры:....97 ✅ На уровне возвращаемого значения:....98 🧠 Зачем это делать?....98 💡 Совет....98 🧩 Хочешь пример "до и после"?....98 ✅ Резюме: как выносить `null` на периферию....99 Предпочитай объединения интерфейсов(union of interfaces)....99 🧩 Принцип:....99 🤔 В чём разница?....99 ❌ Интерфейс с объединением в поле:....100 ✅ Объединение интерфейсов:....100 🧠 Почему это лучше?....100 📌 Запомни:....101 🔄 Как перейти с «интерфейса с объединениями»на объединения интерфейсов?....101 ✅ Пример: API ответ....101 📌 Резюме....102 Использование более узких (строгих)типов вместо `string`....103 🔎 Почему просто `string` — не всегда хорошо?....103 ✅ Как сделать лучше?....103 1. 🔐 Используй **литеральные типы**:....103 2. 🏷️ Используй **брендированные строки** (Branded types)....103 3. 🧩 Используй **шаблонные строковые типы**....104 4. 🗃️ Используй **enum** (если значения фиксированы и нужнычисла)....104 📌 Пример до и после....104 🧠 Резюме: как заменить `string`....105 Использовать отдельный тип дляспециальных значений....105 🧩 Что значит "специальные значения"?....105 ❌ Плохо: использовать обычные значения....105 ✅ Лучше: использовать отдельный тип....106 🔧 Ещё примеры....106 🧾 Пример 1: Специальное значение в результатах....106 💬 Пример 2: Статус загрузки....106 🛡️ Зачем это делать?....107 📌 Используй, когда…....107 🧠 Резюме....107 Ограничить использование опциональныхсвойств....108 🔍 Что значит "ограничить использованиеопциональных свойств"?....108 ❗ Почему чрезмерное использование вредно?....108 ✅ Как ограничивать опциональность?....108 1. **Предпочитай объединения типов с `kind` вместо `?`**....108 2. **Уточняй типы при построении**....109 3. **Или — используй `null`/`undefined` как значение, не какотсутствие**....109 4. **Строго описывай этапы создания объекта**....110 5. **Не делай поля опциональными, если они "появляютсяпозже"**....110 🧠 Резюме....111 Избегайте повторяющихся параметроводного типа....111 ❌ Пример плохой практики....111 ✅ Как избежать?....111 1. 📦 Объединяй параметры в объект с полями....111 2. 🧩 Используй именованные типы....112 3. 🔍 Используй **tuple only if order matters and types aredistinct**....112 4. 🧠 Типы с брендингом (если всё-таки нужно оставитьпозиционность)....112 🧠 Резюме....113 Унификация типов, вместо моделирования....113 🤔 Что это значит?....113 ❌ Плохо: избыточное моделирование различий....113 ✅ Лучше: **унифицированная форма**....114 📦 Пример из API....115 💡 Когда уместна унификация:....115 📌 Принцип....115 🧠 Резюме....116 Лучше неточно, чем недостоверно....116 📌 Что это значит?....116 ❗ Недостоверный тип: опасно....116 ✅ Неточный, но безопасный тип....117 🎯 Когда использовать более **неточный** тип....117 🧠 Пример: API-запрос....118 📌 Идея в одном предложении....118 🧠 Резюме....119 Имена типов на языке предметнойобласти задачи....119 🧠 Что это значит?....119 📌 Пример....119 ❌ Плохо:....119 ✅ Хорошо (на языке предметной области):....119 🛠 Как подбирать имена....120 📦 Пример из интернет-магазина....120 🤝 Зачем это нужно....121 📌 Полезный приём: "задать вопрос"....121 🧠 Резюме....121 Типы на основе API и спецификаций, а неданных....121 🔍 Что значит "генерировать типы поспецификации"?....122 ❌ Плохо: типы по наблюдаемым данным....122 ✅ Хорошо: типы из спецификации....122 🛠 Инструменты для генерации типов....123 🧠 Почему так важно?....123 🔁 Если спецификации нет?....123 📌 Резюме....124 Использовать максимально узкийдиапазон для типов any....124 🔥 Почему `any` опасен?....124 ✅ Как использовать `any` максимально безопасно....125 1. **Ограничь область действия `any` одной переменной**....125 2. **Сужай `any` как можно скорее**....125 3. **Не распространяй `any` в другие типы**....125 4. **Используй `unknown` вместо `any`**....126 5. **Ставь `any` только в точках, где *другого выхода нет***....126 6. **Оборачивай `any`-объекты в валидаторы**....126 🧠 Резюме: как ограничивать `any`....127 Более точные варианты any....127 🛡 Почему не `any`?....127 ✅ Альтернативы `any` — с пояснениями....127 ❌ Чего избегать....128 🔍 Примеры....128 1. `unknown` вместо `any`....128 2. `Record` вместо `any`....128 3. `Partial` — частично известная структура....129 4. Уточнение сигнатуры функции....129 5. Обёртка с `zod` (или другим валидатором)....129 🧠 Резюме....130 Скрывать небезопасные утверждениятипов в хорошо типизированных функциях....130 🎯 Цель....130 ✅ Как это делать правильно....130 1. **Упаковывай небезопасность в маленькие, строготипизированные функции**....131 2. **Пиши обёртки с валидаторами**....131 3. **Скрывай `as` внутри утилит**....132 4. **Сужай `any` и `unknown` до строго определённых типов**....132 5. **Документируй риск, если избежать `as` невозможно**....132 🧠 Резюме....133 unknown вместо any для значений снеизвестным типом....133 🤔 Почему `unknown` лучше, чем `any`?....133 ✅ Как использовать `unknown` правильно?....133 1. Объявляй переменные или аргументы как `unknown`, если незнаешь тип заранее....134 2. Используй проверки типов перед использованием....134 3. Используй пользовательские функции-утверждения (typeguards)....134 4. Используй библиотеки для валидации (`zod`, `io-ts`, `valibot`и т.д.)....134 5. Никогда не делай так:....135 🧠 Резюме....135 Типобезопасные решения вместодинамической модификации....135 🚫 Примеры динамической модификации (плохо вTypeScript)....136 ✅ Альтернативы — типобезопасные подходы....136 1. **Явное создание объектов (сразу целиком)**....136 2. **Чистые функции для изменения объектов (без мутаций)**....136 3. **Mapped types + Record для предсказуемых структур**....136 4. **Функции обновления с типами ключей**....137 5. **Удаление свойств — через утилиты или строгие обёртки**....137 🧠 Резюме....137 Избегайте ловушек надежности....137 🕳️ Что такое "ловушки надёжности"?....138 🔥 Примеры ловушек и как их избегать....138 1. **Использование `any`**....138 2. **Тип `{} ` (пустой объект)**....138 3. **Объектные типы-обёртки (`String`, `Number`, `Boolean`)**....138 4. **Избыточная уверенность через `!` (non-null assertion)**....139 5. **Слепое утверждение типов (`as T`) без проверки**....139 6. **Опциональные поля без проверки**....139 ✅ Общие советы, чтобы не попасть в ловушку....140 Отслеживайте зону охвата типов дляпредотвращения регрессии втипобезопасности....140 💡 Что такое "зона охвата типов"?....140 ✅ Как отслеживать и поддерживать типовую зонуохвата?....141 1. **Включи строгий режим (`strict`)**....141 2. **Избегай `any` и замени их на `unknown`, `never`, `T`,`Partial`, и т.д.**....142 3. **Запрещай `any` через `tsconfig`**....142 4. **Интегрируй линтер (ESLint + TypeScript)**....142 5. **Проверяй границы зон: где типы «теряются»**....142 6. **Пиши больше *type-safe* утилит вместо дублирования**....143 7. **Автоматизируй проверку охвата**....143 🧠 Резюме: как удерживать границытипобезопасности....143 🚀 Продвинутые типы (50-64)....144 Обобщённые (generics) конструкции....144 📌 Простой пример....144 📦 Где рассматривать обобщения в практике....144 🧠 Примеры «обобщённого мышления» в типах....145 1. Обобщённая функция фильтра....145 2. Обобщённый тип ответа API....145 3. Обобщённый компонент в React....145 ✅ Зачем рассматривать обобщения?....146 Избегайте лишних параметров типа....146 📌 В чём проблема с лишними тип-параметрами?....146 ❌ Пример лишнего параметра....146 🛠️ Как распознать и избежать лишнего параметра....147 ✅ Правило 1: Убирай параметр, если его можно вывести....147 ✅ Правило 2: Если параметр никогда не ограничивается — онне нужен....147 ✅ Правило 3: Используй `extends` и `keyof` для ограниченияобобщения....147 ✅ Правило 4: Заменяй одиночные `T` на конкретные типы,если они не должны быть обобщёнными....148 ✅ Правило 5: Используй TypeScript-инференс максимально....148 🧠 Кратко....148 Лучше условные типы, чемперегруженные сигнатуры....148 📌 Что такое перегруженные сигнатуры?....149 ✅ Вместо этого — используем **условный тип** (`Textends X ? A : B`):....149 🧠 Почему это лучше?....150 📌 Пример: вместо перегрузок....150 ❌ Так не надо:....150 ✅ Лучше так:....150 💡 Когда перегрузки всё же полезны?....150 Распределение объединений....150 📦 Что такое **распределение объединений**?....151 🧠 TypeScript распределяет объединение:....151 ✅ Как **управлять распределением**?....151 📌 1. **Распределение включено по умолчанию**....151 📌 2. **Отключить распределение вручную** — оберни `T` вкортеж `[T]`....151 🛠️ Когда нужно включать или отключать?....152 ✅ Распределять — когда нужно **отдельно обработатькаждый тип**:....152 ❌ Не распределять — когда нужно **принять только точныйтип**:....152 🧠 Резюме....152 Шаблонные литеральные типы длямоделирования DSL и отношений междустроками....153 🧩 **Шаблонные литеральные типы в TypeScript**....153 📌 Зачем они нужны?....153 🔧 Синтаксис....153 ✅ Примеры использования....153 ✅ 1. **Моделирование API DSL**....153 ✅ 2. **Маппинг из имени в ключ (CSS, HTML, конфиги, и т.п.)**....154 ✅ 3. **Типизация строк-команд в DSL**....154 ✅ 4. **Отношения между типами строк**....154 ✅ 5. **Ключи объектов по шаблону**....154 🧠 Советы....155 🔍 Проверка формата строки....155 🛠 Пример: генерация сообщений ошибок....155 🔗 Когда это особенно полезно....156 Как писать тесты для типов....156 📌 Способы тестирования типов....156 ✅ 1. **С помощью утилит компилятора (`@ts-expect-error`,`@ts-ignore`, `satisfies`, и др.)**....156 ✅ Пример: проверить, что тип сужается корректно....156 ✅ 2. **С помощью `satisfies`**....156 ✅ 3. **Использовать библиотеки для типовых тестов**....157 🧪 Библиотека [`tsd`](https://github.com/SamVerschueren/tsd)....157 🧪 Альтернатива: [`type-plus`](https://github.com/unional/type-plus)....157 🧠 Самодельные проверки через условные типы....157 🧪 Где писать типовые тесты?....157 ✅ Резюме....158 Обращайте внимание на отображениетипов....158 🔍 Следите за тем, **как вы преобразуете исоздаёте новые типы** на основе других —особенно с помощью **mapped types**(отображаемых типов).....158 🔧 Что такое "отображение типов"?....158 🎯 Зачем **обращать внимание**?....159 📌 Примеры, где это важно....159 ✅ 1. Добавляем модификаторы аккуратно....159 ✅ 2. Убираем модификаторы....159 ✅ 3. Генерируем новые ключи....159 ⚠️ Опасность: не потеряй информацию....160 🧠 Вывод....160 Отдавайте предпочтение обобщеннымтипам с хвостовой рекурсией....160 📘 Что это значит?....160 📌 Пример: рекурсивный тип БЕЗ хвостовойрекурсии....161 ✅ Пример: тот же тип С ХВОСТОВОЙ РЕКУРСИЕЙ(Tail Recursion)....161 🤔 Почему это важно?....161 🎯 Когда использовать?....161 ✅ Пример — `Join<['a', 'b', 'c'], '-'>`....162 🧠 Вывод....162 Кодогенерация как альтернативасложным типам....162 📌 Почему это важно....163 🧠 Примеры ситуаций, когда стоит подумать о**кодогенерации**....163 ✅ Альтернативы: инструменты кодогенерации....163 🛠️ Пример: собственная генерация типов....163 🎯 Преимущества кодогенерации....164 ⚠️ Недостатки....164 💡 Когда **точно** лучше использоватькодогенерацию:....164 ✅ Заключение....165 Типы never для выполнения проверкиполноты....165 🔍 Что значит "проверка полноты"?....165 📌 Пример: дискретное объединение....165 ✅ Проверка с помощью `never`....165 🔒 Как это работает:....166 ✅ То же самое с `if/else`....166 🎯 Зачем это нужно?....166 ⚠️ Частая ошибка: `default` без `never`....167 💡 Функция для проверки....167 📌 Вывод....167 Итерация по объектам....167 🛠 Базовые способы итерации....167 1. `for...in` — по ключам....168 2. `Object.entries`....168 3. `Object.keys`....168 📦 Объект с известной структурой....169 🧠 Итерирование по объекту с динамическимиключами....169 🎯 Полезные типы и утилиты....170 ✅ Рекомендации....170 Типы записей для поддержаниясинхронизации значений....170 📌 Синтаксис `Record`....170 🧠 Применение: синхронизация значений....171 1. 💬 Сопоставление ключей и значений....171 2. ⚙️ Перечисление enum → значения....171 3. ✅ Связывание типов ключей и значений....172 4. 📄 Форма или конфиг как типизированная таблица....172 💡 Почему `Record` помогает держать значениясинхронизированными?....172 🎯 Заключение....173 Остаточные параметры и типы кортежадля моделирования функций спеременным числом аргументов....173 📌 Пример 1: Простая функция с переменнымчислом аргументов....173 📦 Пример 2: Типизация кортежей....173 🎯 Пример 3: Дженерик с кортежем....174 🔄 Пример 4: Перегрузка через условный кортеж....174 🧠 Пример 5: Частичное применение(каррирование)....175 ✅ Когда использовать....175 📌 Вывод....175 Используйте опциональные свойстваnever для моделирования исключающегоИЛИ....176 📌 Что такое исключающее ИЛИ (XOR)?....176 🚫 Почему обычный `A | B` не всегда работает?....176 ✅ Решение: опциональные свойства `never`....176 🔧 XOR через утилиту:....176 Пример:....177 📘 Как это работает?....177 🎯 Когда использовать?....177 📌 Вывод....177 Маркировки для номинальной типизации....178 📘 Что такое номинальная типизация?....178 ✅ Решение: маркировка через `& { __brand: '...' }`....178 🧰 Как создать безопасно?....179 🎯 Где применяют?....179 🧠 Почему это работает?....179 📌 Вывод....179 📦 Публикация и API (65-71)....180 Размещать TypeScript и @types вdevDependencies....180 ✅ Краткий ответ....180 📦 Что такое `devDependencies`?....180 🎯 Почему `typescript` — это devDependency?....180 📦 Почему `@types/...` — это devDependency?....181 ❌ Почему **не стоит** помещать в `dependencies`....181 🧠 Исключения....181 ✅ Вывод....181 Проверять совместимость трех версий,задействованных в объявлениях типов....182 🧩 Что за «три версии»?....182 🎯 Почему это важно?....182 📌 Пример проблемы....182 ✅ Как правильно проверять совместимость....183 1. 📦 Убедитесь, что версия `@types/...` подходит длябиблиотеки....183 2. 🧪 Убедитесь, что `@types/...` совместимы с вашей версиейTypeScript....183 3. 🔧 Заблокируйте версии в `package.json`....183 🧰 Совет: настройка `package-lock.json` или `pnpm-lock.yaml`....184 🧠 Вывод....184 Экспортировать все типы, которыепоявляются в открытом (публичном) API....184 📌 Цель....184 ✅ Что значит «открытый API»?....184 🧱 Пример: библиотека или модуль....185 💡 Надо экспортировать и `AddOptions`!....185 🚨 Почему это важно....185 🧰 Практика: `index.ts` как точка входа....186 🛠 Автоматизация (по желанию)....186 📦 При создании библиотеки (npm-пакета)....186 Важно:....186 🔁 Повторим правило....186 ✅ Чеклист....187 TSDoc для комментариев к API....187 ✍️ Что такое TSDoc?....187 📘 Базовый синтаксис....187 🧠 Куда писать комментарии?....187 🛠 Основные теги TSDoc....188 📦 Пример для интерфейса....188 🧪 Пример с `@example`....189 ⚠️ Важно....189 🔧 Инструменты, совместимые с TSDoc....189 📁 Структура хорошей документации....189 ✅ Резюме....190 Определять тип this в обратных вызовах,если он является частью API....190 🔧 Как указать тип `this` в функциях....190 ✅ Пример:....190 ❌ Почему нельзя использовать стрелочныефункции?....191 ⚙️ Сигнатура с `this` в типе функции....191 🧠 Куда это нужно?....192 📦 Бонус: использование `bind`....192 ✅ Вывод....192 Зеркалирование типов для разрывазависимостей....192 🪞 Что значит "зеркалировать типы"?....193 🔧 Как это выглядит на практике?....193 🎯 Цель: отделить типы от реализации....193 🧠 Трюк: зеркалировать через `typeof`....194 🛠 Альтернативы через маппинг....194 📦 Пример для DTO/API....194 🧩 Когда это полезно?....195 ✅ Советы....195 Аугментацию модулей для улучшениятипов....195 🔧 Пример: Расширение типов `express.Request`....195 💡 Важно:....196 🧩 Пример с собственным модулем....196 🛠 Частый паттерн: расширение глобальныхинтерфейсов....197 📦 Где применяется:....197 ✅ Советы:....197 ⚡ Производительность и миграция (72-83)....198 Отдавать предпочтениефункциональности ECMAScript передTypeScript....198 🧠 Почему?....198 📌 Примеры....198 ✅ Используйте `Array.prototype.map` вместо собственныхутилит с типами:....198 ✅ Используйте `Record` или `Map` вместо своей типовойструктуры:....199 ✅ Используйте `as const` вместо избыточных enum:....199 🔍 Общая идея....199 💬 Когда стоит использовать TypeScript-функциональность?....200 ✅ Вывод....200 Source Map для отладки TypeScript....200 🧩 Что такое Source Map?....200 🛠 Как включить Source Map....200 🧪 Как использовать Source Map в браузере(например, Chrome DevTools)....201 🧠 Пример....201 🛡 Полезно для:....202 🧯 Частые проблемы....202 ✅ Вывод....202 Реконструкция типов на стадиивыполнения....202 🧠 Главный принцип:....203 ✅ Способы реконструкции типов....203 1. 📦 Использование библиотек валидации + типизация....203 2. 🧪 Ручная проверка структуры объектов....203 3. 🧩 Использование декораторов + Reflect Metadata....204 🔄 Идея: тип → схема → валидация → тип....204 📌 Когда нужно реконструировать тип?....205 📦 Рекомендуемые библиотеки....205 🏁 Вывод....205 Иерархия DOM (Document Object Model)....205 🧱 Что такое DOM в контексте TypeScript?....205 🧭 Как получить доступ к DOM-элементам....206 🔹 Способы доступа:....206 🔹 Проверка на null:....206 🔹 Или через non-null assertion (используй осторожно!):....206 🔍 Как работает иерархия DOM в типах....206 Пример:....206 🛠 Работа с детьми, родителями, и соседями....207 🔁 Пример: обход DOM-дерева с типами....207 ✅ Типы элементов....207 ⚠️ Что важно:....208 🧪 Пример: безопасное взаимодействие с формой....208 💡 Заключение....208 Точная модель среды выполнения....208 🧭 Зачем это нужно?....209 🔧 Шаги по созданию точной модели средывыполнения....209 1. **Опиши ожидаемую структуру данных в типах**....209 2. **Проверь данные на соответствие типу (валидация)**....209 ✅ Либо собственную проверку:....209 ✅ Либо использовать библиотеку валидации с выводом типов:....209 3. **Моделируй API/систему строго**....210 4. **Сопровождай типы runtime-валидацией**....210 5. **Не полагайся на типы для сторонних данных**....210 6. **Учитывай платформенные особенности**....211 ✅ Краткий чеклист: точная модель среды....211 💬 Если коротко....211 Проверка типов и юнит-тестирование....211 🧠 В чём разница?....211 🔗 Как они связаны?....212 1. **Типы → Меньше необходимости в тестах на формыданных**....212 2. **Типы помогают писать тесты**....212 3. **Типы ≠ поведение**....212 4. **Типы могут "подсказывать" тест-кейсы**....213 🛠 Лучшее использование — вместе....213 📌 Вывод....213 Быстродействие компилятора....213 🚀 Кратко: как ускорить компиляцию TypeScript....214 📁 1. Разделение на проекты (`Project References`)....214 ⚙️ 2. Настрой `tsconfig.json` для скорости....214 🧠 3. Избегай сложных и дорогих для проверкитипов....215 👀 4. Используй флаг `--watch` и `--incremental`....215 📊 5. Включи `--diagnostics` для анализа....215 🧹 6. Удали неиспользуемые декларации....216 🧰 Инструменты для быстродействия....216 ✅ Вывод....216 Использовать современный JavaScript....217 🚀 1. Используй ES6+ синтаксис....217 📦 2. Работай с асинхронностью через`async/await`....218 🛠 3. Используй современные коллекции....218 🧼 4. Пиши декларативно....218 📚 5. Придерживайся хорошего стиля....218 💡 6. Используй новые фичи стандарта(ECMAScript)....218 🔐 7. Избегай старого и небезопасного....219 ⚙️ 8. Автоматизируй сборку и трансформации....219 🧪 9. Покрывай код тестами....219 🧠 10. Пиши с оглядкой на TypeScript....219 ✨ Хочешь краткую памятку? Вот:....219 📦 ECMAScript-модули (ESM)....220 ✅ Как экспортировать....220 ✅ Как импортировать....220 ✅ Экспорт по умолчанию....220 🏗️ Классы вместо прототипов....221 ✅ Современный синтаксис: `class`....221 Наследование:....221 Почему это важно?....221 🧠 TL;DR....222 @ts-check и JSDoc в TypeScript....222 ✅ Что такое `@ts-check`?....222 ✅ Что такое JSDoc?....222 ✍️ Примеры аннотаций с JSDoc....223 📌 Типизация переменной....223 📌 Массивы....223 📌 Объекты....223 📌 Обобщения (дженерики)....223 📦 Как включить поддержку `@ts-check` в проекте....223 🤓 Рекомендации....224 💡 Пример с `@typedef`....224 ✅ Когда это полезно....224 allowJs для совмещения TypeScript иJavaScript....225 ✅ Как включить `allowJs`....225 🧩 Разница между `allowJs` и `checkJs`....225 🧪 Пример смешанного кода....225 🛠️ Дополнительные советы....226 🧠 TL;DR....226 Конвертируйте модуль за модулем вверхпо графу зависимостей....227 🧠 Что такое граф зависимостей?....227 📈 Что значит «вверх»?....227 🧩 Почему это работает?....227 ✅ Пример пошаговой миграции....228 🔁 Итог....228 Не считайте миграцию завершенной, покане включите noImplicitAny....228 Что такое `noImplicitAny`?....228 Почему это важно?....228 Как выглядит ошибка без `noImplicitAny`....229 Когда включать `noImplicitAny`?....229 Итого....229 📚 Справочные материалы....230 Базовые типы....230 ✅ Примеры:....230 🧊 Особенности....230 1. `string` и `String` — не одно и то же....230 2. `null` и `undefined` — по умолчанию запрещены, если неуказаны явно:....231 3. Литеральные типы....231 🧠 TypeScript добавляет смысл....231 📌 Резюме....232 Дженерики....232 🔹 Зачем нужны дженерики?....232 🔹 Примеры использования....233 1. Функция с дженериком....233 2. Работа с массивами....233 3. Ограничения (`extends`)....233 4. Дженерики в интерфейсах....233 5. Дженерики в классах....234 6. Дженерики с несколькими параметрами....234 ✅ Синтаксис:....234 🔧 Пример 1: преобразование объекта....235 🔧 Пример 2: асинхронная функция....235 🔧 Пример 3: тип функции....235 ⚙️ А если `P` зависит от `T`?....235 📌 Резюме....236 🔹 Итог....236 Cпециальные типы....236 Основные специальные типы:....236 🔍 Подробнее с примерами....237 1. `any`....237 2. `unknown`....237 3. `never`....237 4. `void`....238 📌 Когда что использовать....238Описание
Ниже — практический обзор по теме «книга».
Эта книга — для тех кто уже знаком с javascript, короткое и понятное практическое руководство по TypeScript с примерами и объяснениями на русском языке. Вместо длинных объяснений здесь собраны простые советы, правила и примеры.
Если материал оказался полезен — сохраните страницу.
Поделиться
Частые вопросы
Можно ли скачать «Практический TypeScript» бесплатно?
Да, «Практический TypeScript» доступна для бесплатного скачивания на нашем сайте в формате PDF. Ссылка на файл находится на этой странице.
В каком формате и какого размера файл?
Книга предоставляется в формате PDF, размер файла 2,7 МБ.
Кто автор и когда вышла книга?
автор — Герасимов Александр, издательство Самиздат, год выпуска 2025, 238 страниц.
О чём книга «Практический TypeScript»?
Эта книга — для тех кто уже знаком с javascript, короткое и понятное практическое руководство по TypeScript с примерами и объяснениями на русском языке.