$ sudo teach IT
МОДУЛЬ 1 · УРОК 4

Первый файл .ts и компиляция

Создаём наш первый TypeScript-файл, знакомимся с аннотациями типов и запускаем компиляцию. Шаг за шагом — от пустого файла до работающей программы.

⏱ ~25 минут 🎓 Для новичков 🛠 Практика

📦 Создаём первый файл

Отлично! У нас установлен Node.js и компилятор TypeScript. Пришло время создать наш very первый TypeScript-файл. Это как первый штрих на чистом холсте — здесь начинается всё!

Представьте, что вы — архитектор. У вас есть инструменты (компилятор), чертежи (аннотации типов), и сейчас мы зальём фундамент — создадим файл, в котором будет жить наш первый код. Это важный момент, потому что именно здесь абстрактные знания превращаются в реальную практику.

Шаг 1: Создаём проектную папку

Первым делом нам нужно организовать пространство. Хаос — враг программиста. Создадим отдельную папку для нашего проекта. Это хорошая привычка, которая спасёт вас в будущем, когда проектов станет больше.

Откройте терминал (на macOS это Terminal или iTerm, на Windows — PowerShell или CMD, на Linux — ваш любимый терминал). Затем выполните следующие команды:

💡 Что делает эта команда?

Команда mkdir создаёт новую директорию. Это как открыть новую папку в файловом менеджере, только через командную строку. Флаг -p необязателен здесь, но он полезен, если нужно создать вложенную структуру папок за раз.

mkdir my-typescript-project
cd my-typescript-project

Команда cd (change directory) переводит нас внутрь созданной папки. Теперь все последующие действия будут происходить именно здесь. Как будто мы вошли в кабинет и закрыли за собой дверь — всё, что мы делаем дальше, происходит внутри этого кабинета.

Шаг 2: Инициализируем проект

Теперь создадим файл package.json. Это конфигурационный файл, который описывает наш проект. Он нужен не только для TypeScript — это стандарт в мире Node.js. В этом файле будут храниться метаданные о проекте: название, версия, зависимости и скрипты для запуска.

npm init -y

📌 Полезный совет

Флаг -y означает «да» на все вопросы. npm автоматически заполнит все поля значениями по умолчанию. Вы всегда можете отредактировать этот файл позже в любом текстовом редакторе.

После выполнения команды в папке появится файл package.json с примерно таким содержимым:

{
  "name": "my-typescript-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

Не пугайтесь — большинство этих полей нам пока не нужно. Мы вернёмся к package.json позже, когда начнём настраивать скрипты для автоматической компиляции. Сейчас главное — понимать, что этот файл существует и мы его создали.

Шаг 3: Создаём TypeScript-файл

А вот и момент истины! Создаём наш первый TypeScript-файл. Назовём его hello.ts. Обратите внимание на расширение .ts — это и есть маркер того, что перед нами TypeScript-файл, а не обычный JavaScript.

touch hello.ts

Команда touch создаёт пустой файл. На Windows этой команды нет — просто создайте файл вручную через проводник или текстовый редактор.

⚠️ Важно

Расширение файла — дело серьёзное! Если вы назовёте файл hello.js вместо hello.ts, компилятор TypeScript его не распознает. Всегда проверяйте расширение.

Теперь откройте файл hello.ts в вашем любимом редакторе кода. Если вы следуете нашим рекомендациям из предыдущих уроков, у вас установлен VS Code. Откройте папку проекта в VS Code:

code .

Точка . означает «текущую директорию». Эта команда — сокращение, и она работает, если VS Code установлен в PATH. Если нет, просто откройте VS Code и используйте File → Open Folder.

macOS / Linux

Команда touch hello.ts работает из коробки

Windows

Создайте файл черезправой кнопкой → New → Text Document, затем переименуйте в hello.ts

Все ОС

VS Code создаёт файл автоматически через панель файлов (иконка +)

📝 Пишем код

Файл создан, редактор открыт. Самое время написать наш первый TypeScript-код! Давайте начнём с простого, но важного — функции приветствия и объявления переменных. Это как первое предложение в дневнике: простое, но задающее тон всему, что последует.

Первая функция: greet

Давайте создадим функцию, которая принимает имя и выводит приветствие. Но в отличие от обычного JavaScript, мы добавим нечто новое — аннотацию типа. Посмотрите внимательно на знак : после имени параметра:

function greet(name: string): string {
  return `Привет, ${name}! Добро пожаловать в мир TypeScript!`;
}

// Вызываем функцию
const message = greet("Алексей");
console.log(message);

Давайте разберём каждую часть этого кода:

🔍 Разбор строки по строке

function — ключевое слово для объявления функции. Это как слово «рецепт» в кулинарной книге — оно говорит «сейчас будет инструкция».

greet — имя функции. Выбираете сами, но по соглашению используют camelCase (верблюжий регистр).

name: string — вот он, магический момент! Мы говорим: «параметр name должен быть строкой». Это и есть аннотация типа.

: string после закрывающей скобки — тип возвращаемого значения. Функция обещает вернуть строку.

Шаблонная строка — обратные кавычки ``позволяет`` вставлять переменные через ${}. Удобнее, чем конкатенация с плюсом.

Объявление переменных

Теперь давайте создадим несколько переменных разных типов. Это как расставить разные инструменты на верстаке — каждый имеет свою форму и назначение:

// Строка — текст
const userName: string = "Алексей";

// Число — может быть целым или дробным
const userAge: number = 25;

// Булево значение — true или false
const isStudent: boolean = true;

// Выводим все переменные
console.log("Имя:", userName);
console.log("Возраст:", userAge);
console.log("Студент?", isStudent);

💡 Почему const, а не let?

Используйте const по умолчанию, когда значение не должно меняться. Это помогает избежать случайных ошибок. let используйте только когда точно знаете, что переменная будет переназначаться.

Полный код файла

Давайте объединим всё вместе. Вот как должен выглядеть наш файл hello.ts целиком:

// ============================================
// Мой первый TypeScript-файл
// ============================================

// Функция приветствия
function greet(name: string): string {
  return `Привет, ${name}! Добро пожаловать в мир TypeScript!`;
}

// Переменные с аннотациями типов
const userName: string = "Алексей";
const userAge: number = 25;
const isStudent: boolean = true;

// Используем функцию
const message = greet(userName);

// Выводим результат
console.log(message);
console.log(`Возраст: ${userAge}, Студент: ${isStudent}`);

Сохраните файл (Ctrl+S на Windows/Linux, Cmd+S на macOS). Обратите внимание, как VS Code подсвечивает код — синтаксическая подсветка уже работает, потому что он распознаёт расширение .ts.

⚠️ Не забудьте сохранить!

Компилятор TypeScript читает файл с диска, а не из памяти редактора. Если вы не сохраните файл перед компиляцией, компилятор увидит старую (пустую) версию. Это одна из самых частых ошибок новичков!

🔷 Аннотации типов

Мы уже использовали аннотации типов, но давайте разберёмся глубже. Представьте, что аннотации типов — это как ярлыки на контейнерах. Если на контейнере написано «Мука», вы не будете хранить в нём гвозди. Аналогично, аннотация : string говорит компилятору: «Здесь должна быть строка, ничего другого не суй!»

В мире TypeScript есть три основных примитивных типа, с которых всё начинается. Это как три основных цвета в палитре художника — из них можно смешать всё остальное.

string — строки

Тип string используется для текстовых данных. Это могут быть буквы, цифры (но как текст!), пробелы, эмодзи — в общем, всё, что заключено в кавычки. Кавычки могут быть одинарными, двойными или обратными.

const simpleString: string = "Привет, мир!";
const singleQuotes: string = 'Тоже строка';
const withNumber: string = "Мне 25 лет"; // Это строка, не число!
const empty: string = ""; // Пустая строка — тоже строка
const emoji: string = "🎉 TypeScript!";

// Шаблонные строки (обратные кавычки)
const name: string = "Алексей";
const greeting: string = `Привет, ${name}!`;

Обратите внимание: текст "Мне 25 лет" — это строка, не число, потому что цифры находятся внутри кавычек. TypeScript разбирается в этом безупречно.

number — числа

Тип number охватывает все числа: целые, дробные, положительные, отрицательные, бесконечность и даже специальные значения вроде NaN (Not a Number — забавное название для числового типа, но это историческая особость JavaScript). В TypeScript нет отдельных типов для целых и дробных — всё это number.

const age: number = 25;
const price: number = 19.99;
const negative: number = -42;
const zero: number = 0;
const big: number = 1_000_000; // Подчёркивания для читаемости

// Математические операции
const sum: number = 10 + 20;
const pi: number = 3.14159;

console.log(`Сумма: ${sum}, Pi: ${pi}`);

Забавный факт: подчёркивания в числах (как в 1_000_000) — это просто визуальное разделение тысяч. Компилятор их игнорирует, но человеку гораздо легче прочитать миллион с разделителями.

boolean — логический тип

Тип boolean — это как выключатель: либо включено (true), либо выключено (false). Никаких промежуточных состояний. Это основа логики программирования — каждое условие в конечном счёте сводится к булеву значению.

const isActive: boolean = true;
const isLoggedIn: boolean = false;

// Результат сравнения — тоже boolean
const isGreater: boolean = 10 > 5;    // true
const isEqual: boolean = 5 === 5;   // true
const isNotEqual: boolean = 5 !== 3; // true

// Логические операции
const bothTrue: boolean = true && true;  // true (И)
const eitherTrue: boolean = true || false; // true (ИЛИ)
const notTrue: boolean = !true;         // false (НЕ)

Зачем нужны аннотации типов?

«Подождите, — спросите вы, — если TypeScript и так выводит типы, зачем писать их вручную?» Отличный вопрос! Вот несколько причин:

📖 Читаемость

Другой программист сразу видит, что функция принимает строку и возвращает число. Не нужно читать тело функции.

🛡️ Безопасность

Если вы случайно передадите число туда, где нужна строка, TypeScript поймает ошибку ДО запуска программы.

⚡ Подсказки в IDE

Редактор знает типы и может предлагать автодополнение, показывать ошибки, помогать с рефакторингом.

📚 Документация

Аннотации — живая документация. Они не устаревают, в отличие от комментариев.

💡 Вывод типов

TypeScript может автоматически выводить типы. Если вы напишете const x = 5, TypeScript поймёт, что x — число. Но явные аннотации — хорошая практика для функций и параметров, потому что они служат контрактом.

⚙️ Компиляция

Итак, наш файл написан и сохранён. Теперь самое волшебное — превратим TypeScript в JavaScript! Это как запекать торт: у нас есть тесто (TypeScript), и теперь мы отправляем его в духовку (компилятор), чтобы получить готовое изделие (JavaScript).

Браузеры и Node.js не понимают TypeScript напрямую — они говорят только на JavaScript. Поэтому нам нужен компилятор tsc (TypeScript Compiler), который переводит наш код на язык, понятный исполнителям.

Запуск компилятора

Откройте терминал в папке проекта и выполните:

npx tsc hello.ts

Или, если TypeScript установлен глобально:

tsc hello.ts

Что произойдёт? Компилятор:

🔄 Что происходит при компиляции?

1️⃣ Читает файл hello.ts

2️⃣ Парсит его в абстрактное синтаксическое дерево (AST)

3️⃣ Проверяет типы — соответствуют ли аннотации реальному использованию

4️⃣ Удаляет все аннотации типов (они не нужны в JavaScript)

5️⃣ Генерирует файл hello.js с чистым JavaScript-кодом

6️⃣ Сохраняет hello.js в ту же папку

Проверяем результат

После успешной компиляции в папке появится новый файл hello.js. Посмотрите на содержимое этой папки:

ls -la
# Вывод:
# total 16
# drwxr-xr-x  4 user  staff  128 ...
# -rw-r--r--  1 user  staff  287 ... hello.js
# -rw-r--r--  1 user  staff  312 ... hello.ts
# -rw-r--r--  1 user  staff  345 ... package.json

Отлично! Файл hello.js появился. Теперь давайте запустим его:

node hello.js

В консоли вы увидите:

Привет, Алексей! Добро пожаловать в мир TypeScript!
Возраст: 25, Студент: true

🎉 Поздравляем!

Вы только что создали, скомпилировали и запустили свою первую TypeScript-программу! Это огромный шаг. Вы перешли от теории к практике.

⚠️ Не запускайте .ts файлы напрямую!

Команда node hello.ts НЕ работает (по умолчанию). Node.js не знает, что делать с TypeScript-файлами. Сначала скомпилируйте в JavaScript, затем запускайте .js файл. Позже мы научимся настраивать это автоматически.

🔍 Разбираем вывод

Давайте откроем сгенерированный файл hello.js и посмотрим, что туда попало. Это важный момент — понимание того, что делает компилятор, помогает писать лучший код.

Помните наш TypeScript-код? Вот что из него получилось после компиляции:

// ============================================
// Мой первый TypeScript-файл
// ============================================

// Функция приветствия
function greet(name) {
  return `Привет, ${name}! Добро пожаловать в мир TypeScript!`;
}

// Переменные с аннотациями типов
const userName = "Алексей";
const userAge = 25;
const isStudent = true;

// Используем функцию
const message = greet(userName);

// Выводим результат
console.log(message);
console.log(`Возраст: ${userAge}, Студент: ${isStudent}`);

Заметили главное отличие? Все аннотации типов исчезли! Вот что именно изменилось:

🔎 Что удалил компилятор?

❌ : string после параметра name → стало просто name

❌ : string после скобок → тип возврата удалён

❌ : string, : number, : boolean у переменных → TypeScript автоматически понял типы

✅ Всё остальное осталось без изменений — логика, строки, функции

Это ключевой момент: аннотации типов — это только для разработчика и компилятора. Они не попадают в финальный JavaScript-код. Это как черновик письма — вы правите, редактируете, добавляете пометки, но на чистовике остаётся только чистый текст.

Почему это важно?

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

Кстати, обратите внимание на комментарии в коде — они тоже перешли в JavaScript. Комментарии — единственное «дополнение», которое компилятор не удаляет. Это логично: комментарии нужны и в JavaScript.

Запускаем скомпилированный код

Давайте ещё раз убедимся, что всё работает. Выполните в терминале:

node hello.js

# Вывод:
# Привет, Алексей! Добро пожаловать в мир TypeScript!
# Возраст: 25, Студент: true

Каждый раз, когда вы вносите изменения в hello.ts, вам нужно заново компилировать его командой tsc hello.ts, чтобы обновить hello.js. Это может показаться неудобным, но позже мы настроим автоматическую компиляцию при сохранении файла.

💡 Совет для ленивых (в хорошем смысле)

Программисты по натуре ленивы — и это хорошо! Ручная компиляция утомляет. Позже мы узнаем о флаге --watch, который следит за изменениями и компилирует автоматически. А ещё лучше — настроим npm-скрипт.

🚫 Ошибки компиляции

Ошибки — это не плохо! Ошибки — это как сигнальные огни на приборной панели автомобиля. Они говорят вам, что что-то не так, ПОКА ещё не стало критично. TypeScript ловит ошибки ДО запуска программы — и это его главное преимущество.

Давайте намеренно совершим несколько ошибок и научимся их читать. Это как учиться читать карту: сначала нужно понять символы, потом вы никогда не заблудитесь.

Ошибка 1: Несоответствие типов

Допустим, мы объявили переменную как строку, а пытаемся присвоить ей число:

const userName: string = 42; // ❌ Ошибка!

При компиляции вы увидите:

hello.ts:1:31 - error TS2322: Type 'number' is not assignable to type 'string'.

  const userName: string = 42;
                              ~~

📖 Как читать ошибку TypeScript

hello.ts:1:31 — файл, строка, столбец. Здесь ошибка находится.

TS2322 — код ошибки. Можно загуглить для подробностей.

Type 'number' is not assignable to type 'string' — описание: тип number нельзя присвоить типу string.

Тильды ~~ указывают на проблемное место в коде.

Ошибка 2: Неправильный тип возврата

function getNumber(): number {
  return "Это строка, а не число!"; // ❌ Ошибка!
}

Ошибка:

hello.ts:2:3 - error TS2322: Type 'string' is not assignable to type 'number'.

  return "Это строка, а не число!";
         ~~~~~~~~~~~~~~~~~~~~~~~~~~

Функция обещала вернуть число (: number), а вернула строку. TypeScript не позволяет нарушать контракт.

Ошибка 3: Использование необъявленной переменной

console.log(myVariable); // ❌ Ошибка!

Ошибка:

hello.ts:1:12 - error TS2587: Cannot find name 'myVariable'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.

  console.log(myVariable);
             ~~~~~~~~~~~

TypeScript сразу говорит, что переменная не найдена. В JavaScript такая ошибка возникла бы только при запуске, а в TypeScript — уже при компиляции!

Ошибка 4: Забыли закрыть фигурную скобку

function greet(name: string): string {
  return `Привет, ${name}!`
// Забыли закрыть } !

Ошибка:

hello.ts:3:1 - error TS1005: ';' expected.

TypeScript понимает синтаксис и сразу указывает на проблему. Правда, иногда сообщение может быть неочевидным — но номер строки всегда точный.

Советы по работе с ошибками

1. Читайте номер строки

Первое число после имени файла — номер строки. Идите туда.

2. Читайте описание

TypeScript обычно объясняет проблему простым языком. «Type X not assignable to Y» — значит вы пытаетесь присвоить не тот тип.

3. Гуглите код ошибки

Коды типа TS2322 уникальны. Поисковик выдаст статью с объяснением и решениями.

4. Не паникуйте

Ошибки — это нормально. Даже опытные разработчики видят их десятки раз в день.

💡 Профессиональный подход

Опытные разработчики ЧУВСТВУЮТ типы ошибок. Они видят «TS2322» и сразу знают — несоответствие типов. Вы тоже так научитесь. Через пару недель вы будете интуитивно понимать, что не так, ещё до чтения сообщения об ошибке.

💡 Практический пример

А теперь давайте создадим нечто более реальное. Не просто «Привет, мир!», а полноценный скрипт с несколькими функциями и переменными. Это как перейти от рисования палочек к настоящему эскизу — структура, логика, и всё работает вместе.

Создайте новый файл calculator.ts:

// ============================================
// Простой калькулятор на TypeScript
// ============================================

// Функция сложения
function add(a: number, b: number): number {
  return a + b;
}

// Функция вычитания
function subtract(a: number, b: number): number {
  return a - b;
}

// Функция умножения
function multiply(a: number, b: number): number {
  return a * b;
}

// Функция деления с проверкой на ноль
function divide(a: number, b: number): number {
  if (b === 0) {
    console.log("Ошибка: деление на ноль!");
    return 0;
  }
  return a / b;
}

// Функция возведения в степень
function power(base: number, exponent: number): number {
  return Math.pow(base, exponent);
}

// ============================================
// Используем наши функции
// ============================================

const num1: number = 10;
const num2: number = 5;

console.log("=== Простой калькулятор ===");
console.log(`Числа: ${num1} и ${num2}`);
console.log("");

const sumResult: number = add(num1, num2);
console.log(`Сложение: ${num1} + ${num2} = ${sumResult}`);

const diffResult: number = subtract(num1, num2);
console.log(`Вычитание: ${num1} - ${num2} = ${diffResult}`);

const multResult: number = multiply(num1, num2);
console.log(`Умножение: ${num1} × ${num2} = ${multResult}`);

const divResult: number = divide(num1, num2);
console.log(`Деление: ${num1} ÷ ${num2} = ${divResult}`);

const powResult: number = power(num1, num2);
console.log(`В степень: ${num1} ^ ${num2} = ${powResult}`);

console.log("");
console.log("=== Деление на ноль ===");
divide(10, 0);

Теперь скомпилируйте и запустите:

npx tsc calculator.ts
node calculator.js

Вывод:

=== Простой калькулятор ===
Числа: 10 и 5

Сложение: 10 + 5 = 15
Вычитание: 10 - 5 = 5
Умножение: 10 × 5 = 50
Деление: 10 ÷ 5 = 2
В степень: 10 ^ 5 = 100000

=== Деление на ноль ===
Ошибка: деление на ноль!

💡 Обратите внимание

Мы использовали аннотации типов для всех параметров и возвращаемых значений. Если бы мы случайно попытались передать строку в функцию add, TypeScript немедленно сообщил бы об ошибке при компиляции. Попробуйте!

Более сложный пример: работа со строками

Создадим ещё один файл — на этот раз поработаем со строками и продемонстрируем больше возможностей:

// ============================================
// Утилиты для работы со строками
// ============================================

// Переводим строку в верхний регистр
function toUpper(text: string): string {
  return text.toUpperCase();
}

// Переводим строку в нижний регистр
function toLower(text: string): string {
  return text.toLowerCase();
}

// Считаем количество символов
function countChars(text: string): number {
  return text.length;
}

// Проверяем, является ли строка палиндромом
function isPalindrome(text: string): boolean {
  const lower: string = text.toLowerCase();
  const reversed: string = lower.split("").reverse().join("");
  return lower === reversed;
}

// Обрезаем строку до заданной длины
function truncate(text: string, maxLength: number): string {
  if (text.length <= maxLength) {
    return text;
  }
  return text.substring(0, maxLength) + "...";
}

// ============================================
// Демонстрация
// ============================================

const greeting: string = "Привет, TypeScript!";

console.log(`Оригинал: ${greeting}`);
console.log(`Верхний: ${toUpper(greeting)}`);
console.log(`Нижний: ${toLower(greeting)}`);
console.log(`Длина: ${countChars(greeting)} символов`);
console.log(`Обрезка (10): ${truncate(greeting, 10)}`);

console.log("");
console.log("Палиндромы:");
console.log(`"шалаш" → ${isPalindrome("шалаш")}`);
console.log(`"привет" → ${isPalindrome("привет")}`);
console.log(`"madam" → ${isPalindrome("madam")}`);

Компилируем и запускаем:

npx tsc stringUtils.ts
node stringUtils.js

# Вывод:
# Оригинал: Привет, TypeScript!
# Верхний: ПРИВЕТ, TYPESCRIPT!
# Нижний: привет, typescript!
# Длина: 19 символов
# Обрезка (10): Привет, T...
#
# Палиндромы:
# "шалаш" → true
# "привет" → false
# "madam" → true

🎯 Что мы практиковали?

Аннотации типов для параметров (text: string), возвращаемых значений (: string, : number, : boolean), работу с методами строк, условные конструкции if, и шаблонные строки.

✅ Итоги урока

Что мы сегодня узнали и сделали:

✅ Создали первый TypeScript-файл с расширением .ts

✅ Написали функции с аннотациями типов — параметры и возвращаемые значения теперь имеют явные типы

✅ Изучили три базовых типа: string (строки), number (числа), boolean (логические значения)

✅ Научились компилировать TypeScript в JavaScript командой tsc

✅ Разобрали вывод компилятора — аннотации удаляются, код остаётся чистым JavaScript

✅ Научились читать ошибки компиляции и понимать их структуру

✅ Написали практические примеры — калькулятор и утилиты для строк

✅ Поняли ключевую концепцию: TypeScript — это JavaScript + типы. Компилятор убирает типы и выдаёт чистый JS.

Эти знания — фундамент. На следующем уроке мы узнаем обольше типах данных, которые расширят наши возможности. Вы уже можете писать простые программы на TypeScript и компилировать их — это огромный прогресс!

💡 Рекомендация

Попробуйте поэкспериментировать: создайте собственные функции, поиграйте с типами, намеренно допустите ошибки и посмотрите, как компилятор на них реагирует. Практика — лучший учитель.

Следующий урок →

Урок 5: Типы данных в TypeScript

Проверяем понимание

6 вопросов