Что такое TypeScript и зачем он нужен?

JuniorTypeScript #typescript #basics

Вопрос

Что такое TypeScript, чем он отличается от JavaScript и зачем его использовать?

Короткий ответ

TypeScript — это надмножество JavaScript, добавляющее статическую типизацию. Он не выполняется браузером напрямую: компилятор (tsc) проверяет типы и транспилирует код в обычный JavaScript, после чего типы полностью исчезают — в рантайме их не существует.

Подробный ответ

Любой валидный JavaScript-код является валидным TypeScript-кодом — TS добавляется поверх, а не заменяет язык. Ключевые причины использовать TypeScript:

  • Проверка типов на этапе компиляции. Ошибки вроде обращения к несуществующему свойству или передачи string вместо number находятся до запуска кода, а не в рантайме.
  • Автодополнение и рефакторинг в IDE. Типы дают редактору информацию для подсказок, перехода к определению и безопасного переименования.
  • Документация в коде. Сигнатуры функций и интерфейсы описывают контракт без отдельных комментариев.
  • Типы стираются при компиляции (erasure). В отличие от языков с рантайм-проверкой типов (Java, C#), TypeScript не добавляет никакой проверки типов во время выполнения — весь контроль происходит только на этапе tsc.

TypeScript использует структурную типизацию (structural typing / duck typing), а не номинативную. Совместимость типов определяется формой (набором полей и их типов), а не именем класса или явным объявлением наследования — как в Java или C#, где нужно явно писать implements.

interface Point { x: number; y: number }

function printPoint(p: Point) {
  console.log(`${p.x}, ${p.y}`)
}

// объект нигде не объявлен как Point, но подходит по форме
const vector = { x: 10, y: 20, z: 30 }
printPoint(vector) // OK — лишние поля не мешают, важна лишь совместимость структуры

В номинативной системе типов (Java) этот же вызов потребовал бы явной реализации интерфейса Point. В TypeScript достаточно, чтобы объект структурно удовлетворял требуемой форме.

Пример

// basics.ts
let age: number = 30
let name: string = 'Alice'
let isAdmin: boolean = false

// ошибка обнаруживается на этапе компиляции, а не в рантайме
// age = 'thirty' // Type 'string' is not assignable to type 'number'

function greet(user: { name: string; age: number }): string {
  return `Привет, ${user.name}, тебе ${user.age}`
}

// после компиляции в JS все аннотации типов исчезают:
// function greet(user) { return `Привет, ${user.name}, тебе ${user.age}`; }
console.log(greet({ name, age }))

Дополнительные вопросы

  • Чем структурная типизация отличается от номинативной и где TypeScript всё же ведёт себя "почти номинативно" (например, с приватными полями классов)?
  • Что такое tsconfig.json и за что отвечает флаг strict?
  • Почему TypeScript называют "надмножеством" (superset), а не отдельным языком?