TypeScript это JavaScript с добавленной сверху статической системой типов. Любая программа на JavaScript является корректным синтаксисом TypeScript; TypeScript добавляет аннотации типов, компилятор, который проверяет их до запуска кода, и этап сборки, который снова их удаляет. Во время выполнения остаётся только JavaScript, так что вся разница в том, что вы узнаёте до выпуска кода.
На JavaScript та же функция выглядит так же, только без type Product = ..., : Product[] и : number. Типы добавляют информацию для компилятора и редактора; они не меняют того, что делает программа.
TypeScript и JavaScript: краткое сравнение
| JavaScript | TypeScript | |
|---|---|---|
| Система типов | Динамическая: типы принадлежат значениям и известны только во время выполнения | Статическая: типы объявляются или выводятся и проверяются при компиляции |
| Когда видны ошибки типов | Когда выполняется строка (undefined, NaN, TypeError) | В редакторе при наборе и при компиляции |
| Где работает | Браузеры, Node.js, Deno, Bun, напрямую | Там же, после удаления типов |
| Этап сборки | Не нужен | tsc или бандлер либо среда выполнения, которая сама удаляет типы |
| Файлы | .js, .mjs, .cjs | .ts, .mts, .cts, .tsx, а также объявления типов .d.ts |
| Скорость выполнения | Базовая | Такая же: на выходе JavaScript |
| Поддержка в редакторе | Автодополнение по выведенным типам и типизациям библиотек, которые бывают неполными | Автодополнение, переименование и «найти все ссылки» по объявленным типам |
| Сложность изучения | Ниже | JavaScript плюс система типов |
| Стандарт | ECMAScript, комитет TC39 | Открытый проект Microsoft, который следует за ECMAScript |
Один и тот же код на обоих языках
Вот функция на JavaScript. В ней ничего не говорит о том, как должен выглядеть user:
function greeting(user) {
return `Hello, ${user.firstName} ${user.lastName}`;
}
greeting({ firstname: "Ada", lastName: "Lovelace" });
// "Hello, undefined Lovelace", no error anywhere
Версия на TypeScript один раз описывает структуру, и опечатка обнаруживается до запуска кода:
interface User {
firstName: string;
lastName: string;
}
function greeting(user: User): string {
return `Hello, ${user.firstName} ${user.lastName}`;
}
greeting({ firstname: "Ada", lastName: "Lovelace" });
// error TS2561: Object literal may only specify known properties,
// but 'firstname' does not exist in type 'User'. Did you mean to write 'firstName'?
Аннотации и есть вся разница в синтаксисе. TypeScript также добавляет несколько собственных объявлений (interface, type, enum, дженерики вроде Array<string>, модификаторы доступа вроде private), но инструкции, операторы и встроенные объекты берутся из JavaScript.
Что находит TypeScript и не находит JavaScript
JavaScript молча преобразует типы. Эта ошибка часто встречается со значениями из полей формы, которые всегда являются строками. Запустите код и посмотрите, что скажет компилятор:
index.ts(7,17): error TS2345: Argument of type 'string[]' is not assignable to parameter of type 'number[]'.
Type 'string' is not assignable to type 'number'.
В JavaScript этот код выполнится и напечатает 010205, потому что 0 + "10" это конкатенация строк. TypeScript отказывается компилировать, пока строки не преобразованы, например через fromForm.map(Number).
Другая большая категория это значения, которых может не быть. Array.prototype.find возвращает undefined, если ничего не найдено, и TypeScript заставляет обработать этот случай:
index.ts(8,13): error TS18048: 'user' is possibly 'undefined'.
Версия на обычном JavaScript падает во время выполнения с TypeError: Cannot read properties of undefined (reading 'name'). В TypeScript исправление состоит в обработке случая, на который указал компилятор:
Вывод:
GRACE
no user with id 3
Чего TypeScript не находит: логических ошибок (неверная формула имеет правильный тип) и всего, что касается данных, попадающих в программу во время выполнения. Ответ API с типом User корректен ровно настолько, насколько корректен отправивший его сервер, потому что при выполнении кода типов уже нет. Проверяйте такие данные кодом времени выполнения.
Библиотеки JavaScript в TypeScript
Любой пакет npm работает из TypeScript, потому что на выходе всё равно JavaScript. Типы для пакета берутся из одного из трёх мест:
- Пакет поставляет собственные файлы
.d.ts. Так делают большинство активно поддерживаемых пакетов, и ничего дополнительно ставить не нужно. - Отдельный пакет
@typesиз общественного проекта DefinitelyTyped:npm install --save-dev @types/lodashдобавляет типы дляlodash. - Типов нет. Тогда при включённом
strictошибкой становится сам импорт:
error TS7016: Could not find a declaration file for module 'lodash'. '/project/node_modules/lodash/lodash.js' implicitly has an 'any' type.
Try `npm i --save-dev @types/lodash` if it exists or add a new declaration (.d.ts) file containing `declare module 'lodash';`
Решение: установить пакет @types, если он есть, или описать модуль самостоятельно в файле .d.ts; как это сделать, показано на странице о файлах объявлений.
Этап сборки
Браузеры и Node.js не проверяют типы, поэтому TypeScript нужен шаг между исходным кодом и кодом, который выполняется. Есть три распространённые схемы:
tscкомпилирует всё. Он проверяет типы и записывает файлы.js, обычно в папкуdist. Просто, и это стандарт для библиотек.- Бандлер или dev-сервер удаляет типы, а
tsc --noEmitих проверяет. Vite и esbuild удаляют типы без проверки, поэтому перезагрузка остаётся быстрой; проверку типов запускают редактор и шаг в CI. - Типы удаляет среда выполнения. Современные версии Node.js, Deno и Bun запускают файлы
.tsнапрямую. Ни одна из них не проверяет типы при запуске, поэтому ошибки типов по-прежнему ищут черезtsc --noEmit(илиdeno check).
JavaScript ничего этого не нужно, и для небольших скриптов это его главное практическое преимущество. Цена шага TypeScript это в основном настройка (tsconfig.json и dev-зависимость typescript) и время компиляции; нативный компилятор TypeScript 7 сократил это время примерно в десять раз на больших проектах.
Сложность изучения
Всё, что вы знаете о JavaScript, остаётся в силе, потому что во время выполнения TypeScript это JavaScript. Новое здесь это система типов, и она осваивается слоями:
- Аннотации для переменных, параметров и возвращаемых значений (
: string,: number[]). - Типы объектов через
interfaceиtype, необязательные свойства, объединения вродеstring | number. - Сужение: проверка значения через
typeof,inили===, чтобы компилятор знал, какой случай сейчас действует. - Дженерики, служебные типы вроде
Partial<T>иPick<T, K>и продвинутые типы для авторов библиотек.
Первые два слоя покрывают большую часть прикладного кода. Многие типы выводятся автоматически, поэтому большая часть кода на TypeScript выглядит как JavaScript с аннотациями только в сигнатурах функций.
Когда выбирать TypeScript, а когда JavaScript
TypeScript лучше JavaScript? Для кода, который поддерживают несколько человек или который живёт годами, обычно да, и индустрия движется в эту сторону: по подсчёту GitHub ежемесячных участников, в августе 2025 года TypeScript обогнал и JavaScript, и Python и стал самым используемым языком на GitHub. Для небольших скриптов обычный JavaScript часто оказывается лучшим инструментом.
Выбирайте TypeScript, когда:
- С кодом работает больше одного человека или его будут поддерживать месяцы и годы.
- Кодовая база настолько велика, что все сигнатуры функций не удержать в голове.
- Вы часто делаете рефакторинг: переименование свойства обновляет все использования, а компилятор перечисляет всё, что осталось.
- Вы публикуете библиотеку: файлы
.d.tsдают её пользователям автодополнение и проверки. - Этого ожидает фреймворк. Приложения на Angular пишутся на TypeScript, Next.js и Astro по умолчанию создают новые проекты на TypeScript, а у шаблонов Vite для React, Vue и Svelte есть вариант на TypeScript.
Выбирайте JavaScript, когда:
- Программа это короткий скрипт, разовый эксперимент или фрагмент кода в консоли браузера.
- Вы впервые учитесь программировать и хотите меньше понятий одновременно.
- Этапа сборки нет и вы не хотите его добавлять. Даже тогда
// @ts-checkвместе с JSDoc даёт некоторую проверку в обычном файле.js.
Перевод проекта с JavaScript на TypeScript
Миграцию не обязательно проводить за один раз. Компилятор принимает JavaScript рядом с TypeScript:
{
"compilerOptions": {
"allowJs": true,
"checkJs": false,
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"]
}
С allowJs файлы .js компилируются и могут импортировать из файлов .ts и наоборот. Дальше переводите постепенно:
- Переименуйте один файл из
.jsв.tsи исправьте ошибки, которые компилятор в нём нашёл. - Начинайте с листьев (служебных модулей с небольшим числом импортов), затем двигайтесь внутрь.
- Включите
checkJsили добавьте// @ts-checkв начало отдельных файлов.js, чтобы проверять типы в файлах, которые ещё не переименованы.
В проверяемых файлах JavaScript типы задаются комментариями JSDoc:
// @ts-check
/**
* @param {number} price
* @param {number} qty
* @returns {number}
*/
function lineTotal(price, qty) {
return price * qty;
}
lineTotal("3", 2);
// error TS2345: Argument of type 'string' is not assignable to parameter of type 'number'.
Некоторые команды на этом останавливаются: файлы JavaScript с типами в JSDoc, которые проверяет tsc, и никакого этапа сборки для самого кода. Другие доходят до .ts. Если включить strict в существующем проекте, поначалу ждите много ошибок; на странице о строгом режиме перечислено, что проверяет каждый флаг, чтобы их можно было включать по одному.
Часто задаваемые вопросы
В чём главная разница между TypeScript и JavaScript?
TypeScript добавляет в JavaScript статические типы. Вы описываете, что представляет собой каждое значение (name: string, items: Item[]), и компилятор TypeScript сообщает об ошибках до запуска кода. JavaScript заранее ничего не проверяет: неверный тип проявляется только при выполнении этой строки, часто как undefined или TypeError.
TypeScript лучше, чем JavaScript?
Для большинства проектов, которые поддерживает больше одного человека или которые живут дольше нескольких недель, да: типы ловят целые классы ошибок, делают рефакторинг безопасным и дают редактору автодополнение. Для короткого скрипта, быстрого прототипа или учебного упражнения обычный JavaScript проще начать, и ему не нужна настройка сборки.
TypeScript быстрее, чем JavaScript?
Нет, но и не медленнее. TypeScript компилируется в JavaScript, а типы удаляются, поэтому выполняется тот же JavaScript, который вы написали бы вручную. Единственные дополнительные затраты это время компиляции во время разработки.
Что учить первым: JavaScript или TypeScript?
Изучите основы JavaScript сначала или вместе с TypeScript. Всё поведение во время выполнения (переменные, функции, объекты, массивы, промисы) это JavaScript, а TypeScript лишь описывает его. Когда вы умеете писать небольшие программы на JavaScript, добавить типы уже несложно.
Можно ли использовать TypeScript и JavaScript в одном проекте?
Да. Укажите "allowJs": true в tsconfig.json, и компилятор примет файлы .js рядом с файлами .ts. Добавьте "checkJs": true (или комментарий // @ts-check в отдельных файлах), чтобы проверять типы и в файлах JavaScript по комментариям JSDoc. Так обычно и переводят проект по одному файлу.