← Назад к вопросам

В чем разница между типами any и unknown в TypeScript?

2.0 Middle🔥 231 комментариев
#TypeScript

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Разница между any и unknown в TypeScript

Это один из самых важных различий в TypeScript. any и unknown кажутся одинаковыми, но имеют противоположное поведение. Вот ключевая разница: any отключает проверку типов, unknown требует проверки типов.

Быстрое сравнение

Характеристикаanyunknown
Принимает любой типДаДа
Можно присваивать любому типуДаНет
Можно вызывать методы без проверкиДаНет
Требует type guardНетДа
БезопасенНетДа

any - "Отключить проверку типов"

any означает: "Я не знаю тип, и мне не важно. TypeScript, не проверяй".

let value: any = "hello";
value.toUpperCase(); // OK - работает
value.map(x => x); // OK - работает, хотя это строка!
value.nonExistentMethod(); // OK - работает (но упадёт в runtime!)

const result: string = value; // OK - any присваивается любому типу
const result: number = value; // OK - any присваивается любому типу

С any TypeScript не защищает тебя:

function processData(data: any) {
  data.forEach(item => item.name); // No error!
  // Но если data - не массив, упадёт в runtime
}

processData("not an array"); // TypeError в runtime

unknown - "Неизвестный тип, проверь перед использованием"

unknown означает: "Я не знаю тип, но TypeScript будет требовать проверку перед использованием".

let value: unknown = "hello";
value.toUpperCase(); // ERROR - нужно проверить тип!
value.map(x => x); // ERROR - нужно проверить тип!

const result: string = value; // ERROR - unknown не присваивается строке

С unknown нужна проверка типа (type guard):

let value: unknown = "hello";

if (typeof value === "string") {
  value.toUpperCase(); // OK - теперь TypeScript знает это строка
}

if (Array.isArray(value)) {
  value.forEach(item => item); // OK - теперь это массив
}

Пример: обработка API ответа

Плохо - с any:

const data: any = await fetch('/api/user').then(r => r.json());

// Может привести к runtime ошибкам
data.user.name; // может быть undefined
data.items.forEach(item => item.id); // может быть не массивом

Хорошо - с unknown:

const data: unknown = await fetch('/api/user').then(r => r.json());

if (typeof data === 'object' && data !== null && 'user' in data) {
  console.log(data.user.name); // безопасно
}

if (Array.isArray(data)) {
  data.forEach(item => console.log(item.id));
}

Type guards для unknown

Тип гард - это функция, которая проверяет тип:

// Проверка примитивных типов
let value: unknown;

if (typeof value === 'string') {
  value.toLowerCase(); // OK
}

if (typeof value === 'number') {
  value.toFixed(2); // OK
}

if (typeof value === 'boolean') {
  value === true; // OK
}

Проверка объектов:

interface User {
  id: number;
  name: string;
}

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

const data: unknown = { id: 1, name: 'John' };
if (isUser(data)) {
  console.log(data.name); // OK
}

Проверка массивов:

const data: unknown = ['a', 'b', 'c'];

if (Array.isArray(data)) {
  data.forEach(item => console.log(item)); // OK
}

Практический пример - обработка ошибок

// Плохо
try {
  // код
} catch (error: any) {
  console.log(error.message); // может упасть!
}

// Хорошо
try {
  // код
} catch (error: unknown) {
  if (error instanceof Error) {
    console.log(error.message); // OK
  } else if (typeof error === 'string') {
    console.log(error);
  } else {
    console.log('Unknown error');
  }
}

any vs unknown: когда использовать

Никогда не используй any - это ломает весь смысл TypeScript.

// Плохо
function handleData(data: any) {
  // TypeScript не может помочь
}

// Хорошо
function handleData(data: unknown) {
  // TypeScript требует проверки
  if (typeof data === 'object') {
    // теперь безопасно
  }
}

Используй unknown когда:

  • Получаешь данные из API
  • Обрабатываешь ошибки
  • Работаешь с внешними библиотеками
  • Получаешь JSON
const apiResponse: unknown = await api.getUser();
const errorData: unknown = catch(error);
const externalData: unknown = someLibrary.getData();
const jsonData: unknown = JSON.parse(jsonString);

Почему any опасен

let value: any = 42;
value = "hello"; // OK
value = { name: "John" }; // OK
value.nonExistentMethod(); // OK во время написания, ОШИБКА в runtime

// any распространяется:
const result = value.toUpperCase(); // result: any
result.nonExistentMethod(); // OK - но это ошибка!

unknown требует явной проверки:

let value: unknown = 42;
value = "hello"; // OK
value = { name: "John" }; // OK
value.nonExistentMethod(); // ERROR - нужна проверка!

if (typeof value === 'string') {
  value.toUpperCase(); // OK - проверили
}

Стольная типизация (strict: true)

С strict: true в tsconfig.json:

  • Параметры без типа считаются unknown
  • Методы без явного возврата считаются unknown
  • Требуется более строгая проверка
// С strict: true
// Плохо
function process(data) { // ERROR: implicit any
}

// Хорошо
function process(data: unknown) {
  if (typeof data === 'object') {
    // OK
  }
}

Итог

  • any - отключает проверку типов. Не используй.
  • unknown - требует проверки типов. Используй.

Правило простое: если не знаешь тип, используй unknown и добавь type guard. Это безопаснее и заставляет тебя подумать о возможных значениях.

TypeScript создан, чтобы ловить ошибки. any обходит его защиту. unknown работает с его защитой.