Принцип прапорця: імпорти й експорти лишаються в JavaScript рівно такими, як написані, крім тих, що явно позначені type. Компілятор більше не вирішує сам, які імпорти прибрати.
{ "compilerOptions": { "verbatimModuleSyntax": true } }
Що змінюється:
import { User } from './models.js'; // помилка: User - лише тип, використайте import type
import type { User } from './models.js'; // зникне повністю
import { type User, save } from './api.js'; // лишиться import { save } from './api.js'
import { type User } from './api.js'; // лишиться import {} from './api.js' (модуль завантажиться)
import './polyfills.js'; // лишиться як є
Помилка: «'User' is a type and must be imported using a type-only import when 'verbatimModuleSyntax' is enabled».
Навіщо:
1. Однаковий результат для всіх інструментів. Babel, esbuild, SWC, Vite, стирання типів у Node.js обробляють кожен файл окремо й не знають, чи є імпортована назва типом. Без явних type вони можуть залишити імпорт інтерфейсу (помилка під час виконання) або видалити імпорт, потрібний заради побічних ефектів. З verbatimModuleSyntax результат передбачуваний: що бачите, те й отримаєте.
2. Заміна старих прапорців. Він замінив importsNotUsedAsValues і preserveValueImports, а також бере на себе більшу частину задач isolatedModules.
3. Чіткі межі ESM і CommonJS. У файлах, що компілюються в CommonJS, прапорець забороняє ESM-синтаксис, який не можна перетворити буквально, - потрібно писати import x = require()/export =. Тому для CommonJS-проєктів він незручний; його природне середовище - ES-модулі й збирачі.
Пов'язані прапорці для сучасного проєкту:
isolatedModules- забороняє конструкції, які не можна скомпілювати пофайлово (наприклад, реекспорт типу безexport type);erasableSyntaxOnly- забороняє синтаксис, що потребує генерації коду (enum, parameter properties);- разом із
verbatimModuleSyntaxвони гарантують, що код можна просто «стерти» до JavaScript.
Міграція: правило @typescript-eslint/consistent-type-imports з автовиправленням переписує імпорти за кілька секунд.