Ці три опції часто плутають, хоча вони відповідають на різні питання.
target - у яку версію JavaScript перетворювати синтаксис.
const user = data?.user ?? guest;
З target: "es2019" компілятор перепише ?. і ?? старим синтаксисом, з es2020 і новіше - лишить як є. target змінює лише синтаксис, а не додає відсутні функції (поліфіли).
У TypeScript 6.0+ значення за замовчуванням - останній стабільний стандарт (зараз es2025), а es5 у TypeScript 7 видалено - найнижча ціль тепер es2015. Для старих браузерів TypeScript-код компілюють іншим інструментом.
lib - які вбудовані API існують у середовищі, для перевірки типів:
"lib": ["es2025", "dom", "dom.iterable"]
Без dom компілятор не знає про document і window; без свіжого es20xx - про Array.prototype.toSorted чи Object.groupBy. Якщо lib не вказано, він береться з target (плюс dom). Для коду в Node.js dom зайвий, натомість потрібен пакет @types/node.
Пастка: lib лише описує типи. Вказати es2025, а запускати код у браузері, який цих методів не має, - помилка виконання, яку TypeScript не впіймає.
module - яку систему модулів генерувати (і як трактувати import/export):
esnext/preserve- лишити ES-модулі (типово для коду, який збирає Vite);nodenext- як Node.js: ES-модулі чи CommonJS залежно від"type"уpackage.jsonі розширень файлів;commonjs-require/module.exports.
amd, umd, systemjs і none у TypeScript 7 вже не підтримуються.
Пов'язана опція moduleResolution - як знаходити файли за шляхом в import: bundler для Vite, nodenext для коду, що виконує Node.js.
Для типового Vite-застосунку: target і module мало впливають на результат (код генерує збирач), але lib визначає, які API бачить редактор, - його варто узгодити з браузерами, які ви підтримуєте.