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

Где использовал unknown в TypeScript?

2.0 Middle🔥 201 комментариев
#JavaScript Core#TypeScript

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

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

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

Где использовал unknown в TypeScript

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

Основное различие: any vs unknown

// any — опасно, отключает все проверки типов
const value: any = 'hello';
value.toUpperCase(); // OK (но может быть ошибка!)
value.nonExistentMethod(); // OK (ошибка в runtime!)

// unknown — безопасно, требует проверки типа
const safeValue: unknown = 'hello';
safeValue.toUpperCase(); // ошибка компилятора!
if (typeof safeValue === 'string') {
  safeValue.toUpperCase(); // OK - тип проверен
}

Практические примеры использования

1. Парсинг JSON

Одна из самых частых ситуаций — парсинг JSON, когда структура неизвестна:

// Получаем JSON с сервера, но не уверены в его структуре
const jsonString = '{"user": {"name": "John", "age": 30}}';
const data: unknown = JSON.parse(jsonString);

// Неправильно - компилятор не позволит
// console.log(data.user.name); // ошибка!

// Правильно - с проверкой типа
if (typeof data === 'object' && data !== null && 'user' in data) {
  const user = data.user;
  if (typeof user === 'object' && user !== null && 'name' in user) {
    console.log(user.name); // OK
  }
}

2. Обработка ошибок

В блоке catch неизвестно, какой тип ошибки был выброшен:

try {
  // Какой-то код
  riskyOperation();
} catch (error: unknown) { // unknown, не Error!
  // error может быть Error, String, Number или что угодно
  
  // Нужно проверить тип
  if (error instanceof Error) {
    console.log('Error message:', error.message);
  } else if (typeof error === 'string') {
    console.log('String error:', error);
  } else {
    console.log('Unknown error:', error);
  }
}

3. API ответы

Когда работаешь с API, ответ может иметь разную структуру:

async function fetchData(url: string): Promise<unknown> {
  const response = await fetch(url);
  return response.json(); // unknown
}

// Использование
const data = await fetchData('/api/users/1');

// Нужна проверка типа
function processData(data: unknown) {
  if (typeof data === 'object' && data !== null) {
    if ('id' in data && 'name' in data) {
      // Теперь знаем, что это объект с id и name
      return { id: data.id, name: data.name };
    }
  }
  throw new Error('Invalid data format');
}

4. Event обработчики

В обработчиках событий тип часто неизвестен:

function handleChange(event: unknown) {
  // event может быть Event, какой-то другой тип или null
  
  if (event instanceof Event && event.target instanceof HTMLInputElement) {
    const value = event.target.value;
    console.log('Input value:', value);
  } else if (typeof event === 'object' && event !== null && 'data' in event) {
    console.log('Custom event data:', event.data);
  }
}

5. Функция, которая принимает неизвестный аргумент

// Логирование функция, которая должна логировать что угодно
function logAnything(value: unknown) {
  if (value === null) {
    console.log('null');
  } else if (value === undefined) {
    console.log('undefined');
  } else if (typeof value === 'object') {
    if (Array.isArray(value)) {
      console.log('Array:', value);
    } else if (value instanceof Date) {
      console.log('Date:', value.toISOString());
    } else {
      console.log('Object:', JSON.stringify(value));
    }
  } else if (typeof value === 'function') {
    console.log('Function:', value.name || 'anonymous');
  } else {
    console.log('Value:', value);
  }
}

logAnything(42);
logAnything([1, 2, 3]);
logAnything({ name: 'John' });
logAnything(() => {});

Создание Type Guards

Type guards — функции, которые проверяют тип и уточняют его для TypeScript:

// Type guard функция
function isUser(data: unknown): data is User {
  return (
    typeof data === 'object' &&
    data !== null &&
    'id' in data &&
    'name' in data &&
    typeof (data as any).id === 'number' &&
    typeof (data as any).name === 'string'
  );
}

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

// Использование
const data: unknown = { id: 1, name: 'John' };

if (isUser(data)) {
  // Здесь TypeScript знает, что data это User
  console.log(data.name); // OK
}

Реальный пример из проекта

// API сервис для загрузки данных профессии
interface Profession {
  id: string;
  name: string;
  description: string;
  skills: string[];
}

async function getProfession(id: string): Promise<Profession> {
  const response = await fetch(`/api/professions/${id}`);
  const data: unknown = await response.json();
  
  // Валидируем неизвестные данные
  if (!isProfession(data)) {
    throw new Error('Invalid profession data');
  }
  
  return data; // Теперь TypeScript знает, что это Profession
}

function isProfession(data: unknown): data is Profession {
  return (
    typeof data === 'object' &&
    data !== null &&
    'id' in data &&
    'name' in data &&
    'description' in data &&
    'skills' in data &&
    typeof (data as any).id === 'string' &&
    typeof (data as any).name === 'string' &&
    typeof (data as any).description === 'string' &&
    Array.isArray((data as any).skills)
  );
}

// Использование
const profession = await getProfession('frontend');
console.log(profession.name); // TypeScript гарантирует, что это строка

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

СитуацияИспользуй
Тип неизвестен, но нужна безопасностьunknown
Нужна максимальная гибкость (редко)any
Данные с сервера / JSONunknown
Ошибки в catch блокеunknown
Обработка user inputunknown
Динамические событияunknown

Лучшие практики

// ПЛОХО - использование any
function process(data: any) {
  return data.foo.bar; // Может сломаться, TypeScript не помогает
}

// ХОРОШО - использование unknown с проверкой
function process(data: unknown): string {
  if (typeof data === 'object' && data !== null && 'foo' in data) {
    const foo = data.foo;
    if (typeof foo === 'object' && foo !== null && 'bar' in foo) {
      return foo.bar;
    }
  }
  throw new Error('Invalid data structure');
}

// ОТЛИЧНО - использование Type Guard
function isValidData(data: unknown): data is { foo: { bar: string } } {
  return (
    typeof data === 'object' &&
    data !== null &&
    'foo' in data &&
    typeof (data as any).foo === 'object' &&
    (data as any).foo !== null &&
    'bar' in (data as any).foo &&
    typeof (data as any).foo.bar === 'string'
  );
}

function process(data: unknown): string {
  if (!isValidData(data)) {
    throw new Error('Invalid data structure');
  }
  return data.foo.bar; // Теперь TypeScript знает тип
}

Вывод

unknown использую в::

  1. Парсинге JSON — данные с сервера неизвестной структуры
  2. Обработке ошибок — catch блоки, где может быть что угодно
  3. API интеграции — когда ответ от API может быть разным
  4. Обработке пользовательского ввода — валидация форм и данных
  5. Event обработчиках — тип события может быть неизвестен
  6. Логировании — функции, которые логируют что угодно

unknown — это правильный выбор для безопасности типов. Это заставляет разработчика явно проверить тип перед использованием, что предотвращает ошибки на runtime.