Приведение типов

Приведение типов (type assertion) в TypeScript — это механизм, с помощью которого разработчик явно указывает компилятору, какого типа значение на самом деле является. Это не влияет на выполнение кода (типы исчезают при транспиляции), но помогает обойти ограничения вывода типов в ситуациях, когда программист знает больше, чем компилятор.

Когда нужно приведение типов

Часто возникает при работе с DOM, API или динамическими структурами, где TypeScript не может точно определить тип:

const element = document.getElementById("my-input");
// Тип element: HTMLElement | null

element.value; // Ошибка: HTMLElement не имеет свойства value

Здесь мы знаем, что элемент — это <input>, но TypeScript видит только общий тип HTMLElement. Чтобы получить доступ к value, нужно уточнить тип.

Способы приведения типов

1. Синтаксис с угловыми скобками (устаревший)

const input = <HTMLInputElement>document.getElementById("my-input");

Этот синтаксис не работает в JSX/TSX (например, в React), поэтому его избегают.

2. Синтаксис с as

const input = document.getElementById("my-input") as HTMLInputElement;
console.log(input.value); // теперь доступно

Этот вариант совместим с JSX и считается стандартом.

Важные ограничения

Приведение типов не выполняет проверок во время выполнения. Оно говорит компилятору: «доверься мне». Если предположение неверно — ошибка проявится только при запуске:

const elem = document.getElementById("some-div") as HTMLInputElement;
console.log(elem.value); // ошибка во время выполнения, если это не input

Поэтому приведение следует использовать осторожно и только тогда, когда вы уверены в типе.

Приведение к более общему типу

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

function logElement(el: HTMLElement) {
  console.log(el.tagName);
}

const button = document.querySelector("button") as HTMLButtonElement;
logElement(button as HTMLElement); // безопасно: HTMLButtonElement ⊂ HTMLElement

В таких случаях приведение корректно, так как иерархия типов соблюдена.

Альтернатива: проверка типов

Если вы не уверены в типе, лучше использовать проверку вместо приведения:

const el = document.getElementById("my-input");
if (el instanceof HTMLInputElement) {
  console.log(el.value); // безопасно, без приведения
}

Этот подход сохраняет безопасность TypeScript и предпочтителен при работе с неопределёнными данными. Но из-за того что instanceof не работает с обычными объектами, созданных через литерал {} а только с конструкторами (классами или функции-конструкторы) - в рамках этого предмета мы не будем использовать данный оператор.