Чим відрізняється 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>
);
}
Порівняльна таблиця
| Характеристика | JavaScript | TypeScript |
|---|---|---|
| Типізація | Динамічна | Статична |
| Перевірка помилок | Під час виконання | Під час компіляції |
| Розмір файлів | Менший | Більший (через типи) |
| Швидкість розробки | Швидший старт | Повільніший старт, швидша розробка |
| Автодоповнення | Обмежене | Повне |
| Навчання | Простіше | Складніше спочатку |
| Рефакторинг | Ризиковий | Безпечний |
| Підтримка в командах | Складніша | Легша |
Коли використовувати що?
Обирайте 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 стає стандартом для серйозних проектів, тому його вивчення - це інвестиція у вашу кар'єру розробника!