beginnertypescriptjavascripttypescompilationstatic-typing

Чим відрізняється TypeScript від JavaScript?

Детальний розібір відмінностей між TypeScript та JavaScript з прикладами і порівняннями

Чим відрізняється TypeScript від JavaScript?

Уявіть, що JavaScript - це як писати листа від руки, а TypeScript - як писати на комп'ютері з автокорекцією. Обидва дають результат, але TypeScript допомагає уникнути помилок ще до того, як ви їх зробите.

Простими словами

JavaScript - це мова програмування, яка працює у браузерах і на сервері. Вона динамічна і гнучка.

TypeScript - це JavaScript з додатковими можливостями. Головна відмінність - типи даних, які допомагають знайти помилки на етапі написання коду.

Основні концепції

JavaScript - динамічна типізація

// JavaScript - типи визначаються під час виконання
let message = "Привіт"; // string
message = 42; // тепер number
message = true; // тепер boolean

function greet(name) {
  return "Привіт, " + name;
}

// Можна передати що завгодно
greet("Олег"); // "Привіт, Олег"
greet(123); // "Привіт, 123"
greet(null); // "Привіт, null"

TypeScript - статична типізація

// TypeScript - типи визначаються під час компіляції
let message: string = "Привіт"; // тільки string
// message = 42; // ❌ Помилка! Cannot assign number to string

function greet(name: string): string {
  return "Привіт, " + name;
}

// Тільки string як аргумент
greet("Олег"); // ✅ Працює
// greet(123); // ❌ Помилка! Argument of type 'number' is not assignable

Детальне порівняння

1. Перевірка типів

JavaScript

// Помилки виявляються тільки під час виконання
function calculateArea(width, height) {
  return width * height;
}

calculateArea(10, 20); // 200 - працює
calculateArea("10", "20"); // "1020" - неочікуваний результат!
calculateArea(); // NaN - помилка під час виконання

TypeScript

// Помилки виявляються під час компіляції
function calculateArea(width: number, height: number): number {
  return width * height;
}

calculateArea(10, 20); // ✅ 200
// calculateArea("10", "20"); // ❌ Помилка компіляції
// calculateArea(); // ❌ Помилка компіляції

2. Автодоповнення та IntelliSense

JavaScript

// Обмежене автодоповнення
const user = {
  name: "Марія",
  age: 25,
  email: "maria@example.com"
};

// IDE не знає точно, які властивості є в user
user. // показує загальні методи Object

TypeScript

// Повне автодоповнення
interface User {
  name: string;
  age: number;
  email: string;
}

const user: User = {
  name: "Марія",
  age: 25,
  email: "maria@example.com"
};

// IDE точно знає структуру
user. // показує: name, age, email з правильними типами

3. Об'єктно-орієнтоване програмування

JavaScript (ES6+)

class Animal {
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(`${this.name} издає звук`);
  }
}

class Dog extends Animal {
  speak() {
    console.log(`${this.name} гавкає`);
  }
}

TypeScript з модифікаторами доступу

abstract class Animal {
  protected name: string;
  
  constructor(name: string) {
    this.name = name;
  }
  
  abstract speak(): void;
  
  // Приватний метод
  private logAction(action: string): void {
    console.log(`${this.name} ${action}`);
  }
}

class Dog extends Animal {
  public speak(): void {
    this.logAction("гавкає"); // ✅ Доступ до protected
    console.log(`${this.name} гавкає`);
  }
}

// const animal = new Animal("тварина"); // ❌ Cannot create instance of abstract class

4. Інтерфейси та контракти

JavaScript - неформальні домовленості

// Сподіваємося, що об'єкт має потрібні властивості
function processUser(user) {
  // Надіємося, що user має name та email
  console.log(`Processing ${user.name} (${user.email})`);
}

TypeScript - формальні контракти

interface User {
  readonly id: string;
  name: string;
  email: string;
  age?: number; // необов'язкова властивість
}

function processUser(user: User): void {
  // user.id = "new-id"; // ❌ Cannot assign to readonly property
  console.log(`Processing ${user.name} (${user.email})`);
}

// Гарантується, що user має всі потрібні властивості

5. Сучасні можливості

Generics (Узагальнення)

// Універсальна функція для роботи з різними типами
function getFirstItem<T>(items: T[]): T | undefined {
  return items[0];
}

const numbers = [1, 2, 3];
const strings = ["a", "b", "c"];

const firstNumber = getFirstItem(numbers); // number | undefined
const firstString = getFirstItem(strings); // string | undefined

Union та Intersection типи

// Union - може бути одним з типів
type Status = "loading" | "success" | "error";

// Intersection - має бути всіма типами одночасно
type User = {
  name: string;
} & {
  email: string;
};

// Умовні типи
type ApiResponse<T> = T extends string 
  ? { message: T } 
  : { data: T };

type StringResponse = ApiResponse<string>; // { message: string }
type NumberResponse = ApiResponse<number>; // { data: number }

Процес розробки

JavaScript

// 1. Пишемо код
function addNumbers(a, b) {
  return a + b;
}

// 2. Запускаємо у браузері/Node.js
// 3. Знаходимо помилки під час виконання
console.log(addNumbers("5", "10")); // "510" - ups!

TypeScript

// 1. Пишемо код з типами
function addNumbers(a: number, b: number): number {
  return a + b;
}

// 2. Компілюємо в JavaScript
// tsc script.ts → script.js

// 3. Помилки знаходяться ДО запуску
// addNumbers("5", "10"); // ❌ Помилка компіляції

Практичні приклади

API запити

JavaScript

// Без гарантій щодо структури відповіді
async function fetchUser(id) {
  const response = await fetch(`/api/users/${id}`);
  const user = await response.json();
  
  // Сподіваємося, що user має name
  return user.name?.toUpperCase();
}

TypeScript

interface ApiUser {
  id: string;
  name: string;
  email: string;
  createdAt: string;
}

interface ApiResponse<T> {
  data: T;
  success: boolean;
  message?: string;
}

async function fetchUser(id: string): Promise<string | null> {
  const response = await fetch(`/api/users/${id}`);
  const result: ApiResponse<ApiUser> = await response.json();
  
  if (result.success) {
    return result.data.name.toUpperCase(); // ✅ Гарантовано існує
  }
  
  return null;
}

React компоненти

JavaScript

// Невідомо, які props очікуються
function UserCard({ user, onEdit }) {
  return (
    <div>
      <h2>{user.name}</h2>
      <button onClick={() => onEdit(user.id)}>
        Редагувати
      </button>
    </div>
  );
}

TypeScript

interface User {
  id: string;
  name: string;
  email: string;
}

interface UserCardProps {
  user: User;
  onEdit: (userId: string) => void;
}

function UserCard({ user, onEdit }: UserCardProps): JSX.Element {
  return (
    <div>
      <h2>{user.name}</h2>
      <button onClick={() => onEdit(user.id)}>
        Редагувати
      </button>
    </div>
  );
}

Порівняльна таблиця

ХарактеристикаJavaScriptTypeScript
ТипізаціяДинамічнаСтатична
Перевірка помилокПід час виконанняПід час компіляції
Розмір файлівМеншийБільший (через типи)
Швидкість розробкиШвидший стартПовільніший старт, швидша розробка
АвтодоповненняОбмеженеПовне
НавчанняПростішеСкладніше спочатку
РефакторингРизиковийБезпечний
Підтримка в командахСкладнішаЛегша

Коли використовувати що?

Обирайте JavaScript якщо:

  • ✅ Невеликий проект або прототип
  • ✅ Команда не знайома з TypeScript
  • ✅ Потрібен швидкий запуск
  • ✅ Проект має багато динамічного коду
  • ✅ Використовуєте багато сторонніх бібліотек без типів

Обирайте TypeScript якщо:

  • ✅ Середній або великий проект
  • ✅ Працює команда розробників
  • ✅ Важлива довгострокова підтримка
  • ✅ Потрібна надійність та стабільність
  • ✅ Активний рефакторинг коду
  • ✅ Складна бізнес-логіка

Міграція з JavaScript на TypeScript

Крок 1: Налаштування

# Встановлення TypeScript
npm install -D typescript @types/node

# Створення tsconfig.json
npx tsc --init

Крок 2: Поступова міграція

// 1. Перейменовуємо .js в .ts
// 2. Додаємо базові типи
// 3. Поступово покращуємо типізацію

// Було (JavaScript)
function processData(data) {
  return data.map(item => item.value * 2);
}

// Стало (TypeScript - крок 1)
function processData(data: any) {
  return data.map((item: any) => item.value * 2);
}

// Стало (TypeScript - крок 2)
interface DataItem {
  value: number;
}

function processData(data: DataItem[]): number[] {
  return data.map(item => item.value * 2);
}

Підсумок

TypeScript - це еволюція JavaScript, яка додає:

  • 🛡️ Безпеку типів
  • 🚀 Кращу продуктивність розробки
  • 🔧 Потужні інструменти розробки
  • 📚 Самодокументований код
  • 🏗️ Кращу архітектуру додатків

JavaScript залишається простішим для:

  • ⚡ Швидких прототипів
  • 🎯 Малих проектів
  • 🏃 Швидкого старту

У сучасній розробці TypeScript стає стандартом для серйозних проектів, тому його вивчення - це інвестиція у вашу кар'єру розробника!