any, unknown и never
Три специальных типа на краях системы: лазейка any, страховка unknown и тупик never.
any отключает проверку типов, unknown требует проверить значение перед использованием, never означает «значения не будет никогда».
any — лазейка, отключающая типы
Тип any говорит компилятору «не проверяй здесь ничего». С такой переменной можно делать что угодно — и потерять всю защиту:
let data: any = "строка";
data.foo.bar.baz; // компилятор молчит
data(); // молчит
data * 10; // молчит
Любая из этих строк рухнет в рантайме, но TypeScript не предупредит. По сути any возвращает нас в обычный нетипизированный JavaScript. Поэтому правило простое: избегайте any, особенно его неявного появления (для этого и нужен noImplicitAny из строгого режима).
unknown — безопасная альтернатива
Когда тип значения действительно заранее неизвестен (например, ответ внешнего API), берут unknown. В него можно записать что угодно, как в any, но использовать его, не проверив, нельзя:
let value: unknown = fetchData();
value.toUpperCase();
// Ошибка: 'value' is of type 'unknown'.
if (typeof value === "string") {
value.toUpperCase(); // ок — внутри проверки тип сузился до string
}
Разница принципиальна: any снимает ответственность с программиста, unknown — заставляет проверить значение. Это превращает потенциальный рантайм-баг в обязательную проверку.
any против unknown
| Свойство | any | unknown |
| Принимает любое значение | да | да |
| Можно использовать без проверки | да (опасно) | нет |
| Сохраняет безопасность типов | нет | да |
never — то, чего не бывает
Тип never описывает значение, которого не может существовать. Он появляется у функций, которые никогда не возвращают управление — например, всегда бросают исключение или зацикливаются:
function fail(message: string): never {
throw new Error(message);
}
Функция не возвращает значение в обычном смысле — она прерывает выполнение. Тип void здесь не подошёл бы: void значит «вернёт undefined», а never — «не вернёт вообще ничего».
Где never полезен на практике
never помогает гарантировать, что вы обработали все варианты. Если в switch по union-типу появится необработанный случай, присвоение в never вызовет ошибку компиляции — это «проверка на полноту»:
type Status = "ok" | "error";
function handle(s: Status): string {
switch (s) {
case "ok": return "Успех";
case "error": return "Ошибка";
default:
const _exhaustive: never = s; // если добавят новый статус — здесь ошибка
return _exhaustive;
}
}
Итог
anyотключает проверку типов — используйте как крайнюю меру.unknown— безопасный «неизвестный тип»: требует проверки перед использованием.never— значения не существует; помогает функциям без возврата и проверке полнотыswitch.