TypeScript
October 24

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

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

Что такое any?

Тип any в TypeScript представляет собой самый гибкий и свободный тип. Он говорит компилятору: "Я разрешаю делать с этой переменной всё, что угодно". Когда вы используете any, TypeScript фактически отключает проверку типов для этой переменной, позволяя ей принимать любые значения и выполнять любые операции.


Пример использования any:

let value: any;
value = "Привет";
value = 42;
value = { a: 1, b: 2 };

console.log(value.toUpperCase()); 
// Ошибка выполнения, если value не строка

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

Что такое unknown?

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

Пример использования unknown:

let value: unknown;
value = "Привет";
value = 42;
value = { a: 1, b: 2 };

// value.toUpperCase(); // Ошибка компиляции

if (typeof value === 'string') {
  console.log(value.toUpperCase()); // Теперь можно безопасно вызвать метод
}

В этом примере TypeScript не позволяет нам использовать метод toUpperCase без предварительной проверки типа переменной. Это добавляет дополнительный шаг, но делает код гораздо безопаснее.


Отличие unknown от any

  1. Проверки перед использованием: Если с типом any можно делать всё без ограничений, то unknown требует проверки типа перед выполнением операций.
  2. Безопасность: Использование unknown значительно снижает вероятность ошибок на этапе выполнения, поскольку компилятор не позволит вам использовать переменную до тех пор, пока вы не убедитесь в её типе.
  3. Явные проверки типов: Работа с unknown вынуждает разработчиков явно проверять и преобразовывать типы, что делает код более читаемым и предсказуемым.

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

  • Ввод данных от пользователей: Если ваше приложение получает данные из внешних источников (например, формы, API, или файлов), и вы не уверены в типах этих данных, лучше использовать unknown. Это позволяет вам безопасно обрабатывать данные после проверки их типа.
  • Функции с переменными типами: Если функция принимает значения, типы которых могут варьироваться, unknown поможет вам правильно обработать их, избегая ошибок.

Пример функции с использованием unknown:

function handleInput(input: unknown) {
  if (typeof input === 'string') {
    console.log("It's a string:", input.toUpperCase());
  } else if (typeof input === 'number') {
    console.log("It's a number:", input.toFixed(2));
  } else {
    console.log("Unknown type:", input);
  }
}


Почему unknown предпочтительнее any?

  1. Контроль над кодом: Использование unknown заставляет разработчиков быть более внимательными и проверять типы данных перед их использованием.
  2. Повышенная безопасность: Так как unknown запрещает операции без проверки типа, это предотвращает многие распространенные ошибки.
  3. Прозрачность и поддерживаемость кода: Программы с явными проверками типов легче поддерживать и читать. Если тип данных проверяется и преобразуется, будущие разработчики смогут быстрее понять логику.


Как использовать unknown в TypeScript

Чтобы максимально эффективно использовать unknown, старайтесь всегда проверять тип данных перед выполнением операций. Это можно сделать с помощью стандартных операторов typeof, instanceof или конструкций типа "пользовательских защитников типов".

function isString(value: unknown): value is string {
  return typeof value === 'string';
}

function processValue(value: unknown) {
  if (isString(value)) {
    console.log("It's a string:", value.toUpperCase());
  } else {
    console.log("Not a string:", value);
  }
}