Система статической типизации 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}');