Система статичної типізації TypeScript надбудовується над рантаймом JavaScript у вигляді шару стирання типів (Type Erasure). Усі типи, інтерфейси та анотації існують виключно на етапі компіляції в AST (Abstract Syntax Tree) і повністю видаляються під час транспіляції в чистий JavaScript. Це означає нульовий оверхед у рантаймі: типи не збільшують розмір бандлу і не уповільнюють виконання програми.
Фундаментом системи виступають примітивні типи: string, number, boolean, bigint, symbol, null та undefined. На відміну від примітивів об'єктних обгорток JavaScript (String, Number, Boolean), примітивні типи в TypeScript пишуться строго з малої літери та представляють неподільні атомарні значення.
Ключовим механізмом ергономіки TypeScript є автоматичне виведення типів (Type Inference). Компілятор використовує контекстний аналіз потоку управління (Control Flow Analysis) та алгоритм уніфікації для самостійного визначення найбільш вузького безпечного типу змінної без необхідності надмірного ручного анотування.
У TypeScript існує фундаментальний поділ між змінними (let, var) та константами (const). Цей поділ безпосередньо визначає стратегію виведення типів компілятора:
+-------------------------------------------------------------------------+
| МЕНТАЛЬНА МОДЕЛЬ ВИВЕДЕННЯ ТИПІВ (Inference) |
+-------------------------------------------------------------------------+
| let status = 'pending' ---> Тип: string (Type Widening) |
| (Може змінитися в майбутньому) Допустимо присвоїти будь-який рядок |
+-------------------------------------------------------------------------+
| const status = 'pending' ---> Тип: 'pending' (Literal Type) |
| (Ніколи не зміниться) Вузький підтип string з одного слова |
+-------------------------------------------------------------------------+
| const config = { port: 3000 } ---> Тип: { port: number } |
| (Об'єкт константний за посиланням, Властивості мутабельні! |
| але поля можна перезаписати) Потрібен "as const" для глибокого утримання |
+-------------------------------------------------------------------------+as const)
Парсер перетворює вихідний код в AST. Вираз ініціалізації пов'язується з ідентифікатором змінної.
Компілятор аналізує модифікатор оголошення: для `const` обчислюється літеральний тип, для `let` застосовується Type Widening.
При наступних операціях компілятор звіряє тип нового значення з виведеним типом за правилами структурної сумісності.
Емітер компілятора видаляє всі анотації та генерує чистий JS-код без будь-яких поліфілів перевірки типів.
Який тип отримає змінна `theme` у наступному виразі: `const theme = 'dark'`?
'GET' | 'POST' | 'PUT' | 'DELETE' замість розмитого типу string.variant: 'primary' | 'secondary' | 'ghost').symbol та bigint для високоточних фінансових транзакцій та унікальних глобальних ключів.as const, що унеможливлює одруківки в сегментах URL на етапі компіляції.У JavaScript існують примітиви ('hello', 42, true) та відповідні їм об'єктні обгортки (new String('hello')). У TypeScript використання типів String, Number, Boolean, Object з великої літери вважається грубою помилкою:
// ПРАВИЛЬНО: використання примітивних типів
const username: string = 'alex_dev';
const retryCount: number = 3;
const isProduction: boolean = true;
const transactionId: bigint = 9007199254740991n;
const uniqueKey: symbol = Symbol('node_id');
// НЕПРАВИЛЬНО: типи-обгортки описують інстанси класів, а не примітивні значення!
// let badString: String = 'bad'; // Антипатерн!Компілятор автоматично звужує тип при використанні const і розширює при використанні let:
let userRole = 'admin'; // Тип: string (можна перепризначити userRole = 'viewer')
const defaultRole = 'admin'; // Тип: 'admin' (літеральний тип)
function assignPermission(role: 'admin' | 'moderator') {
console.log(`Access granted for ${role}`);
}
assignPermission(defaultRole); // Коректно: 'admin' сумісний з 'admin' | 'moderator'
// ПОМИЛКА КОМПІЛЯЦІЇ:
// assignPermission(userRole);
// TS2345: Argument of type 'string' is not assignable to parameter of type ''admin' | 'moderator''.as const#За замовчуванням поля об'єктів розширюються (widening), навіть якщо сам об'єкт оголошено як const:
// Без 'as const': властивості мутабельні
const defaultSettings = {
endpoint: 'https://api.wpskills.dev/v1',
timeout: 5000,
logLevel: 'info', // Тип поля: string!
};
// defaultSettings.logLevel = 'debug'; // Дозволено компілятором!
// З застосуванням 'as const': глибокий readonly та літеральні типи
const safeSettings = {
endpoint: 'https://api.wpskills.dev/v1',
timeout: 5000,
logLevel: 'info',
} as const;
// Тип safeSettings:
// {
// readonly endpoint: "https://api.wpskills.dev/v1";
// readonly timeout: 5000;
// readonly logLevel: "info";
// }
// safeSettings.timeout = 10000; // ПОМИЛКА TS2540: Cannot assign to 'timeout' because it is a read-only property.Чому компілятор видає помилку при передачі `config.method` у функцію `fetchData(config.url, config.method)`, якщо `method: 'POST'` всередині об'єкта `const config = { url: '/api', method: 'POST' }`?
Типи String, Number, Boolean з великої літери описують не примітиви, а інстанси вбудованих JS-конструкторів. Значення примітиву не є повноцінним екземпляром Object, що викликає неочікувані помилки сумісності:
// ПОМИЛКА:
function format(id: String) { /* ... */ }
// ПРАВИЛЬНО:
function format(id: string) { /* ... */ }Завжди використовуйте виключно назви примітивів з малої літери.
Написання let count: number = 0 або const name: string = 'Alice' є шумом коду. Компілятор безпомилково обчислює типи тривіальних виразів. Анотуйте типи лише там, де виведення неможливе (параметри функцій, порожні масиви, складні типи, що повертаються).
Оголошення змінної як any відключає перевірку типів компілятора для всього низхідного потоку операцій:
// НЕБЕЗПЕЧНО: компілятор мовчить, додаток падає в рантаймі!
const rawPayload: any = JSON.parse('{"status": 200}');
rawPayload.unknownMethod(); // TypeError в рантаймі!
// ПРАВИЛЬНО: використовуйте unknown з подальшою валідацією
const safePayload: unknown = JSON.parse('{"status": 200}');Використання any повністю ламає типобезпеку та суворо заборонено стандартами кодової бази.