Menu

TypeScript и JavaScript: разница и ключевые отличия

TypeScript это JavaScript плюс статическая система типов, которая проверяется до запуска кода. Сравниваем их бок о бок: синтаксис, что находит проверка типов, этап сборки, скорость, сложность изучения и как перевести проект с JavaScript на TypeScript.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

TypeScript это JavaScript с добавленной сверху статической системой типов. Любая программа на JavaScript является корректным синтаксисом TypeScript; TypeScript добавляет аннотации типов, компилятор, который проверяет их до запуска кода, и этап сборки, который снова их удаляет. Во время выполнения остаётся только JavaScript, так что вся разница в том, что вы узнаёте до выпуска кода.

На JavaScript та же функция выглядит так же, только без type Product = ..., : Product[] и : number. Типы добавляют информацию для компилятора и редактора; они не меняют того, что делает программа.

TypeScript и JavaScript: краткое сравнение

JavaScriptTypeScript
Система типовДинамическая: типы принадлежат значениям и известны только во время выполненияСтатическая: типы объявляются или выводятся и проверяются при компиляции
Когда видны ошибки типовКогда выполняется строка (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. Новое здесь это система типов, и она осваивается слоями:

  1. Аннотации для переменных, параметров и возвращаемых значений (: string, : number[]).
  2. Типы объектов через interface и type, необязательные свойства, объединения вроде string | number.
  3. Сужение: проверка значения через typeof, in или ===, чтобы компилятор знал, какой случай сейчас действует.
  4. Дженерики, служебные типы вроде 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 и наоборот. Дальше переводите постепенно:

  1. Переименуйте один файл из .js в .ts и исправьте ошибки, которые компилятор в нём нашёл.
  2. Начинайте с листьев (служебных модулей с небольшим числом импортов), затем двигайтесь внутрь.
  3. Включите 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. Так обычно и переводят проект по одному файлу.

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ