Веб-разработка
TypeScript для веба
В 2023 году Airbnb опубликовал что TypeScript предотвращает 38% их production bugs. Stripe строит весь свой SDK на TypeScript с strict mode - тип ошибки в payment API стоит миллионы. Не случайно что крупнейшие JavaScript проекты (React, Vue, Next.js, Node.js) мигрировали или создавались на TypeScript.
- **Figma** переписал весь frontend с Flow на TypeScript strict - команда из 100 инженеров заметила что pull requests стали проходить review на 30% быстрее за счёт types как документации
- **Vercel** использует TypeScript generics для создания type-safe Next.js API routes - тип route params и response автоматически проверяются без ручной валидации
- **tRPC** построен на TypeScript conditional types и generics - end-to-end type safety между backend и frontend без кодогенерации, только TypeScript
Strict Mode
TypeScript strict mode - флаг включающий группу проверок: strictNullChecks (нельзя присвоить null там где ожидается значение), noImplicitAny (нельзя использовать implicit any), strictFunctionTypes, strictPropertyInitialization. Без strict mode TypeScript даёт ложное чувство безопасности - половина ошибок рантайма остаётся незамеченной.
Чаще всего встречаемые ошибки при включении strict: 'Object is possibly null/undefined' (strictNullChecks), 'Parameter implicitly has any type' (noImplicitAny), 'Property not initialized in constructor' (strictPropertyInitialization). Решения: optional chaining `?.`, nullish coalescing `??`, type guards, non-null assertion `!` (использовать осторожно).
Почему strictNullChecks - наиболее важная опция в TypeScript strict mode?
Generics
Generics - параметрический полиморфизм в TypeScript: функции и классы работают с разными типами сохраняя типобезопасность. `<T>` - параметр типа. Constraints `<T extends SomeType>` ограничивают какие типы допустимы. Generic функции часто лучше union types для переиспользуемого кода.
Conditional types `T extends U ? X : Y` - сильный инструмент для type-level programming. `infer` - извлечение типа из другого типа. Template literal types `${Prefix}${string}` - строковые типы с паттерном. Эти возможности используются для создания type-safe API клиентов, роутеров и ORM (Drizzle, Prisma, tRPC).
Что означает `K extends keyof T` в generic constraint?
Utility Types
TypeScript встроенные utility types трансформируют существующие типы. Наиболее используемые: `Partial<T>` (все свойства опциональны), `Required<T>` (все обязательны), `Pick<T, K>` (выбрать свойства), `Omit<T, K>` (исключить свойства), `Readonly<T>` (запрет мутации), `Record<K, V>` (словарь), `NonNullable<T>` (исключить null/undefined).
Практичные комбинации: `Partial<Pick<User, 'name' | 'email'>>` - форма обновления только части полей. `Omit<User, 'password'>` - публичный профиль без секретных полей. `Record<Status, number>` - счётчики по статусам. `ReturnType<typeof myFunction>` - тип возвращаемого значения функции. `Awaited<ReturnType<...>>` - тип Promise результата.
Зачем использовать `Omit<User, 'password'>` вместо создания нового интерфейса PublicUser вручную?
Declaration Files (.d.ts)
Declaration files (.d.ts) описывают типы JavaScript библиотек без TypeScript исходников. `@types/react`, `@types/node` - из DefinitelyTyped репозитория. Кастомные .d.ts для: добавления типов к legacy JS коду, описания глобальных переменных, module augmentation (расширение существующих типов без изменения исходников).
Module augmentation - продвинутая техника: расширение типов Express Request, добавление свойств к `process.env`, типизация кастомных событий. `declare global` для глобальных типов. `/// <reference types='...' />` для подключения type references. Ambient declarations: описывают существующие значения без их реализации.
TypeScript full strict mode замедляет разработку из-за большого количества type errors
Первые 2-3 дня есть friction при миграции существующего кода. В долгосрочной перспективе strict TypeScript ускоряет разработку: IDE autocomplete работает точнее, рефакторинг безопаснее, review быстрее (types как документация), меньше runtime bugs
Исследования Microsoft показывают что TypeScript предотвращает 15-38% runtime bugs; время экономии на debugging > время на написание типов
Зачем нужен module augmentation для `process.env`?
Ключевые идеи
- **Strict mode** - необходимая основа; strictNullChecks предотвращает самый частый класс TypeError; noUncheckedIndexedAccess ловит array out-of-bounds
- **Generics** - type-safe переиспользуемый код; `<T extends keyof U>` для type-safe property access; conditional types для type-level programming
- **Utility Types + Declaration Files** - Partial/Omit/Pick для API DTO без дублирования; module augmentation для расширения Express/process.env типов
Связанные темы
TypeScript интегрирован во все современные web инструменты:
- State Management — Redux Toolkit, Zustand и Pinia имеют excellent TypeScript support; generic types обеспечивают type-safe dispatch и selectors
- Тестирование: Jest, Playwright — TypeScript в тестах: type-safe mocks, typed test fixtures; ts-jest для компиляции TypeScript тестов
Вопросы для размышления
- Если в проекте 50000 строк JavaScript без TypeScript - как организовать миграцию на strict TypeScript постепенно без остановки разработки?
- Когда conditional types и infer оправданы в production коде, а когда это over-engineering?
- Как module augmentation для process.env помогает в production когда переменная окружения не задана?