# P20 · октябрь 2019 · миграция JavaScript на TypeScript — тройное ревью
Статус: **принят в публикационный слой 31 июля 2026 года**. Registry применяет
три revision по стабильным slug и сохраняет дату и автора базового архива:
- editorial-2019-10-practice-typescript-migration;
- editorial-2019-10-mechanism-typescript-migration;
- editorial-2019-10-field-typescript-migration.
Модуль экспортирует ровно три revision без полей date и
author. При прямом вызове с --print-revisions он
печатает только JSON, совпадающий с import-safe export. В статьях типы,
fixture и метрики показаны как методы проверки; ни один вымышленный
production-результат не выдан за измерение.
## Проход 1. Факты и техника — пройдено
| Утверждение или решение | Первичный источник | Проверенная граница |
| --- | --- | --- |
| JavaScript-синтаксис допустим в TypeScript, поэтому файл можно переносить постепенно, а не одномоментно | [TypeScript Handbook: Migrating from JavaScript](https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html) | Практика не обещает массовое переименование; в маршруте сохранены соседние JavaScript-модули |
| TypeScript-специфичные конструкции не становятся runtime-проверкой после компиляции | [TypeScript Handbook: Migrating from JavaScript](https://www.typescriptlang.org/docs/handbook/migrating-from-javascript.html), [TypeScript 3.5 release notes](https://devblogs.microsoft.com/typescript/announcing-typescript-3-5/) | В механизме type alias отделён от исполняемого normalizer; сетевой payload не объявлен проверенным только из-за interface |
| allowJs принимает JavaScript-файлы рядом с TypeScript, что подходит для поэтапного переноса | [TSConfig: allowJs](https://www.typescriptlang.org/tsconfig/allowJs.html) | Конфигурация fixture держит allowJs и noEmit; она не меняет format модулей и output production-сборки |
| checkJs выдаёт diagnostics для JavaScript; локальный @ts-check позволяет начать с одного файла | [TSConfig: checkJs](https://www.typescriptlang.org/tsconfig/checkJs.html) | В practice и field @ts-check стоит в одном boundary-файле, а не выдаётся за включение проверки всего legacy-дерева |
| TypeScript 3.5 уже содержит нужную для примера эпоху: проверку JavaScript, unknown, type predicates и релизные изменения вокруг generic checking | [TypeScript 3.5 release notes](https://devblogs.microsoft.com/typescript/announcing-typescript-3-5/) | Нет позднего синтаксиса, satisfies, optional chaining, Zod, современных стратегий Node module resolution или заявлений зрелости 2027 года |
### Честная граница фикстур
Код normalizer проверяет учебный объект Member и предназначен для
трёх контролируемых входов: валидный объект, объект без email и
объект с чужим status. Он показывает, где runtime-код должен
остановить неясный payload. Фикстура не вызывает реальный API, не измеряет
скорость сборки и не подтверждает ответ конкретной сетевой библиотеки.
Конфигурация с noEmit — безопасный первый режим проверки, а не
совет заменить существующий delivery pipeline. Если конкретный проект
генерирует JavaScript через tsc, интегратор обязан отдельно
сопоставить target, module, output path и реальную
production-команду. Этот риск в статьях назван ограничением, а не скрыт
обещанием «переход пройдёт безболезненно».
Вердикт прохода: **пройден**. Технические утверждения привязаны к официальным
источникам TypeScript, а свойства, зависящие от конкретного проекта, оставлены
явными задачами проверки.
## Проход 2. Редактура и голос М2 / 2019 — пройдено
| Ревизия | Симптом и цена в начале | Главный вопрос | Практический артефакт и ограничение |
| --- | --- | --- | --- |
| Практика | Массовый rename создаёт any и останавливает выпуск; цена — длинная ветка без полезной проверки данных | Как начать миграцию с границы и сохранить build | tsconfig fixture, JSDoc normalizer, таблица границ и выпускной маршрут; процент .ts не выдан за качество |
| Механизм | Файл уже .ts, но неверный payload доходит до экрана; цена — место ответственности скрыто за any | Почему типы исчезают в runtime и где ставить проверку | сравнение исходника и JavaScript, normalizer unknown → Member, таблица ролей; статический анализ не выдан за runtime-защиту |
| Полевой разбор | Legacy transport отдаёт response.body напрямую; цена — неясный откат и риск сломать delivery | Как перенести один поток без массового rewrite | автономная fixture transport → normalizer → screen и четыре gate; нет заявления о запуске реального сервера |
- Первые два абзаца каждой статьи называют симптом, проблему и стоимость
неверного маршрута. Дальше текст держит цепочку: симптом → причина →
проверка → действие → ограничение.
- Речь короткая и техническая: вместо общих оценок названы
allowJs, checkJs, noEmit,
unknown, any, normalizer, contract fixture,
type-check и build gate.
- Автор соответствует М2 / 2019: он уже связывает frontend-код, delivery и
API-границу, но не приписывает себе поздние практики платформенной команды,
SLO, современную схему валидации или зрелую организационную программу
миграции.
- Три текста не дублируют друг друга: практика задаёт маршрут, механизм
разбирает исчезновение типов и роль any, полевой разбор
собирает минимальную выпускную партию.
- Объём, число разделов, таблица с caption/thead,
код, упорядоченный маршрут, figure с alt/caption и два или больше источника
подлежат независимой автоматической проверке draft gate.
Вердикт прохода: **пройден**. Тексты сохраняют практический голос автора
2019 года и не подменяют решение эффектными обещаниями.
## Проход 3. Визуал и выпуск — пройдено в пределах автономного пакета
- typescript-migration-lane-2019.svg показывает четыре малых
шага: baseline выпуска, границу данных, локальный @ts-check и
один TypeScript-модуль; выпускные gate вынесены в нижний блок. Визуал не
предлагает переписать всё дерево файлов.
- typescript-migration-type-boundary-2019.svg противопоставляет
нормальный путь unknown → runtime normalizer → Member красному
обходу через any. Это уточняет границу ответственности, а не
дублирует таблицу из статьи.
- typescript-migration-release-gates-2019.svg отделяет contract
fixture, type-check, существующий build и smoke. Четыре карточки прямо
показывают, что один успешный gate не доказывает остальные.
- У всех SVG есть title, desc,
role="img" и aria-labelledby. В статьях
предусмотрены самостоятельные содержательные alt-тексты и
figcaption. SVG не содержат JavaScript, внешних URL,
foreignObject или растровых data URI.
- Независимый мобильный preflight отрисовал каждый SVG через Sharp в PNG
шириной 375 px. Первый вариант двух схем содержал слишком мелкие вторичные
подписи. Их заменили на вертикальные композиции с короткими подписями;
повторный рендер не показал обрезания, наложения или горизонтального
выхода. Это проверка статичных схем, а не browser-review страницы.
- После подключения registry строгий аудит подтвердил три revision, а
production build сгенерировал 374 статические страницы. Реальный browser
review остаётся отдельной проверкой поведения и не заявлен как выполненный.
### Фактические проверки
Запускаются следующие независимые проверки:
node --check web/scripts/upgrade-2019-10.mjs
cd web && npm run audit:draft -- scripts/upgrade-2019-10.mjs
xmllint --noout \
web/public/assets/editorial/2019/typescript-migration-lane-2019.svg \
web/public/assets/editorial/2019/typescript-migration-type-boundary-2019.svg \
web/public/assets/editorial/2019/typescript-migration-release-gates-2019.svg
Результат независимого запуска 31 июля 2026 года:
| Проверка | Результат |
| --- | --- |
| node --check | PASS, синтаксис модуля корректен |
| --print-revisions и import-safe export | PASS внутри draft gate: stdout — только JSON, export совпадает с CLI и содержит ровно три revision |
| npm run audit:draft -- scripts/upgrade-2019-10.mjs | PASS: 9 756 / 9 495 / 10 347 знаков основного текста; у каждого текста есть проблема в начале, пять или больше разделов, figure, таблица, код, маршрут и источники |
| xmllint --noout для трёх SVG | PASS, XML корректен |
| Strict audit после подключения registry | PASS: 9 756 / 9 495 / 10 347 знаков; по одному figure и table, по два code example |
| npm run build | PASS, code 0, 374 статические страницы |
| Scope/self-review | PASS: в revision нет date/author; в SVG нет script, foreignObject, внешних ссылок или data URI; articles.json не перезаписан |
Выпусковой вердикт: **тройное ревью пройдено, пакет принят к публикации**.
articles.json не менялся; registry заменяет только редакционные
поля по стабильному slug. Поведение на реальной странице в выбранном браузере
нужно проверить отдельно: production build и raster preflight этого не
подменяют.