Дайджесты новостей
Макрокомпозиция архитектурного моста Content Mappers, связывающего компоненты Vue с нативным компилятором TypeScript 7 на Go.

TypeScript 7.1 Content Mappers: прямая проверка типов в Vue без vue-tsc

Если ты разрабатываешь интерфейсы на Vue 3 с использованием TypeScript, то наверняка помнишь, какой болью долгие годы сопровождалась проверка типов в Single File Components (.vue).

Поскольку официальный компилятор tsc от Microsoft исторически ничего не знал про файлы с расширением .vue и умел работать только с .ts и .tsx, сообществу приходилось выкручиваться. Так появился пакет vue-tsc — хитроумная надстройка авторства создателя проекта Volar Джонсона Чу. Утилита занималась изощрённым monkey-patching: она на лету перехватывала внутренние методы Node.js-рантайма компилятора TypeScript, подсовывала виртуальные файлы и выдавала ошибки наружу.

Работало это медленно, регулярно ломалось при обновлениях минорных версий языка и создавало зоопарк форков. Но настоящий кризис грянул, когда Microsoft полностью переписала компилятор TypeScript 7 на язык Go ради десятикратного ускорения сборки. Старый трюк с подменой методов в JavaScript-рантайме компилятора в одночасье стал технически невозможным.

Ответом на этот вызов стал официальный механизм TypeScript 7.1 Content Mappers, подробный разбор которого опубликовал разработчик Алекс Опа в издании VueDigest. Механизм открывает прямую нативную поддержку сторонних форматов файлов прямо в компиляторе tsc.

Исторический тупик: как vue-tsc ломал компилятор и почему Go всё изменил

Чтобы оценить масштаб прорыва, давай заглянем под капот старой схемы с vue-tsc.

Когда запускалась команда vue-tsc --noEmit, процесс запускал отдельный инстанс Node.js. Утилита читала файл .vue, парсила его на три секции (<template>, <script> и <style>), генерировала из шаблона искусственный виртуальный TypeScript-код рендер-функции с сохранением sourcemaps и через приватные недокументированные API компилятора инжектировала этот виртуальный код в дерево зависимостей.

Накладные расходы были чудовищными:

  • Потребление оперативной памяти на больших монорепозиториях легко пробивало потолок в 4–8 гигабайт.
  • В CI/CD пайплайнах проверка типов занимала по 3–5 минут, из-за чего многие команды отключали шаг typecheck на pre-commit хуках, пропуская глупые ошибки в прод.
  • Несоответствие версий: ты мог обновить typescript в проекте, но vue-tsc внутри тянул старый движок, из-за чего свежие фичи синтаксиса TS не работали в шаблонах.

Переход TypeScript 7 на нативный бинарник на Go поставил сообщество перед фактом: либо мы получаем официальный API плагинов в tsc, либо Vue навсегда остаётся без проверки типов в новой версии компилятора. Команда TypeScript пошла навстречу фронтенд-экосистеме и внедрила Content Mappers.

Анатомия Content Mappers: виртуальный код и нативный вызов tsc

Как устроен новый механизм? Теперь компилятор tsc сам умеет делегировать чтение нестандартных файлов внешним мапперам через секцию plugins в конфигурационном файле tsconfig.json.

Когда tsc натыкается на файл MyComponent.vue, он передаёт его содержимое зарегистрированному плагину @vue/language-plugin-content-mapper. Плагин преобразует шаблон и блок <script setup lang="ts"> в виртуальный TypeScript-файл в памяти компилятора. Все позиции символов и номера строк точно привязываются к оригинальному файлу .vue.

В результате проверка типов запускается напрямую через официальный компилятор:

# Прямая нативная проверка типов в проекте Vue через официальный tsc
tsc --noEmit --runExternalCode

Никаких сторонних бинарников и форков компилятора. Если проверка прошла успешно, ты на 100% уверен, что код соответствует спецификации TypeScript.

Флаг runExternalCode

Параметр --runExternalCode обязателен: компилятор TypeScript требует явного подтверждения от разработчика на запуск внешнего JavaScript-плагина маппера в процессе сборки.

Бенчмарк на базе Directus: 4.6-кратное ускорение и 1100 строгих ошибок

Разработчик Алекс Опа провёл масштабный эксперимент, переведя на TypeScript 7.1 Content Mappers кодовую базу популярной headless-CMS Directus — проекта с сотнями сложных Vue-компонентов, кастомных директив и сервисных модулей.

Результаты бенчмарка оказались ошеломляющими:

  • Скорость проверки типов: время полного прогона тайпчека сократилось в 4.6 раза по сравнению с vue-tsc. То, что раньше подвешивало консоль на пару минут, теперь отрабатывает за считанные секунды.
  • Строгость типизации: новый пайплайн выявил более 1 100 ошибок против 445, которые находил старый vue-tsc.

Почему ошибок стало больше? Старый vue-tsc из-за ограничений monkey-patching делал множество эвристических допущений и закрывал глаза на несовпадения типов в краевых случаях шаблонов. Нативный компилятор tsc проверяет типы пропсов, событий $emit и слотов с бескомпромиссной строгостью.

Пошаговая настройка tsconfig.json и переход на новый стандарт

Для миграции существующего проекта на Vue 3 достаточно трёх простых шагов:

  1. Удаляем vue-tsc и устанавливаем свежий TypeScript и языковой плагин:
npm uninstall vue-tsc
npm install -D typescript@^7.1.0 @vue/language-plugin-content-mapper@next
  1. Подключаем плагин маппинга контента в секции compilerOptions в файле tsconfig.json:
{
  "compilerOptions": {
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "noEmit": true,
    "plugins": [
      {
        "name": "@vue/language-plugin-content-mapper",
        "extensions": [".vue"]
      }
    ]
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.d.ts",
    "src/**/*.vue"
  ]
}
  1. Обновляем команду в секции scripts файла package.json:
{
  "scripts": {
    "typecheck": "tsc --noEmit --runExternalCode"
  }
}

Появление Content Mappers — поворотный момент для всей экосистемы Vue. Компоненты .vue наконец-то стали полноправными гражданами мира TypeScript, избавившись от шатких прокладок и подарив разработчикам невероятную скорость проверок в CI/CD.