unknown vs any в TypeScript: что выбрать в 2025 году?

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение: почему эта тема взорвала Stack Overflow?

Если вы когда-нибудь писали на TypeScript, то наверняка сталкивались с дилеммой: unknown или any? Вопрос, собравший тысячи просмотров на Stack Overflow, не теряет актуальности и в 2025 году. Кажется, что оба типа позволяют хранить что угодно — так в чём же разница?

Представьте, что вы строите дом. any — это дверь, открытая настежь для всех, включая грабителей. unknown — дверь с замком и видеоглазком: вы сначала проверите, кто пришёл, а потом уже пускаете. В этой статье мы разберёмся, почему unknown стал золотым стандартом безопасности в TypeScript, а any — злом, которое иногда бывает оправдано.

Мы не просто перескажем документацию. Мы покажем реальные кейсы из практики 2025 года, разберём лучшие практики и дадим чёткий алгоритм выбора. Поехали!

Что такое any и почему его все боятся?

any — это самый "гибкий" тип в TypeScript. Он буквально говорит компилятору: "Отключи систему типов, я знаю, что делаю". Звучит как суперсила, но на деле это бомба замедленного действия.

Пример: как any ломает типы

function processUser(user: any) {
    console.log(user.name.toUpperCase()); // Ошибка в рантайме, если user — null
}

processUser(null); // TypeError: Cannot read property 'toUpperCase' of null

Компилятор TypeScript даже не предупредит вас об этом! any отключает все проверки, и ошибка вылезет только в продакшене. В 2025 году, когда проекты становятся сложнее, такой подход — путь к хаосу.

Когда any всё-таки полезен?

  • Миграция с JavaScript: когда вы переписываете старый проект, any — временный костыль.
  • Динамические данные: например, ответы от внешних API, где структура меняется.
  • Тесты: в моках иногда проще использовать any, чем описывать сложные типы.

Но помните: any — это как кредитная карта с бесконечным лимитом. Удобно, пока не придёт счёт.

Unknown: строгий охранник на входе

unknown появился в TypeScript 3.0 как безопасная альтернатива any. Он тоже может содержать любое значение, но запрещает с ним работать без явной проверки. Это тип-контейнер, который требует верификации.

Пример: unknown в действии

function processUser(user: unknown) {
    // Ошибка компиляции! Свойство 'name' не существует на типе 'unknown'
    // console.log(user.name.toUpperCase()); 
    
    // Нужна проверка
    if (user && typeof user === 'object' && 'name' in user) {
        const typedUser = user as { name: string };
        console.log(typedUser.name.toUpperCase()); // Всё ок
    }
}

processUser({ name: "Alice" }); // ALICE
processUser(null); // Ничего не упадёт

Заметили разницу? unknown не даёт вам стрелять себе в ногу. Вы обязаны проверить тип перед использованием. Это и есть безопасная типизация.

Сравнение any vs unknown в таблице

Чтобы закрепить материал, давайте посмотрим на ключевые отличия:

Критерий any unknown
Присвоение любого значения ✅ Да ✅ Да
Доступ к свойствам без проверки ✅ Да ❌ Нет
Присвоение другому типу ✅ Любому ❌ Только any или unknown
Защита от ошибок в рантайме ❌ Нет ✅ Да (требует проверки)

Как видите, unknown побеждает по всем пунктам безопасности. Но есть нюанс...

Лучшие практики 2025: когда что использовать

Опираясь на опыт сообщества и реальные проекты, вот чек-лист для принятия решения:

Используйте unknown, если:

  • Вы получаете данные из ненадёжного источника (API, пользовательский ввод, JSON).
  • Вы пишете библиотеку и хотите, чтобы пользователь сам проверял типы.
  • Вы работаете с рекурсивными или гетерогенными структурами данных.

Используйте any, если:

  • Вы мигрируете с JavaScript и не хотите переписывать всё сразу.
  • Вы пишете прототип или хак для хакатона (но обещайте потом переписать!).
  • Вы работаете с рефлексией или метапрограммированием, где типы физически нельзя проверить.

Но самый важный совет на 2025 год: избегайте any в коде, который пойдёт в продакшен. Используйте unknown + type guards (защитники типа).

Продвинутые техники работы с unknown

В 2025 году сообщество выработало несколько паттернов, которые делают работу с unknown удобной и элегантной.

Паттерн 1: Type guard-функции

function isUser(obj: unknown): obj is { name: string; age: number } {
    return (
        typeof obj === 'object' &&
        obj !== null &&
        'name' in obj &&
        'age' in obj &&
        typeof (obj as any).name === 'string' &&
        typeof (obj as any).age === 'number'
    );
}

function greet(user: unknown) {
    if (isUser(user)) {
        console.log(`Привет, ${user.name}! Тебе ${user.age} лет.`);
    } else {
        console.log('Это не пользователь');
    }
}

Такие функции можно переиспользовать во всём проекте. Это как создать свой собственный "швейцарский нож" для проверки типов.

Паттерн 2: Z-схема (Zod или Yup)

В 2025 году валидация на уровне рантайма стала стандартом де-факто. Библиотеки вроде zod позволяют описать схему и автоматически вывести тип:

import { z } from 'zod';

const UserSchema = z.object({
    name: z.string(),
    age: z.number().positive(),
});

type User = z.infer<typeof UserSchema>;

function processUnknown(data: unknown): User {
    const result = UserSchema.safeParse(data);
    if (!result.success) {
        throw new Error('Невалидные данные');
    }
    return result.data; // Тип                

Блоги

Рекомендаций по книгам