8

'unknown' против 'any': в чем разница?

1

Описание проблемы:

В TypeScript 3.0 был введен новый тип unknown. Согласно официальной документации:

unknown теперь является зарезервированным названием типа, так как это встроенный тип. В зависимости от вашего предполагаемого использования unknown, вы можете удалить объявление этого типа полностью (предпочтя новый тип unknown), или переименовать его во что-то другое.

Возникает вопрос: в чем разница между типами unknown и any? Когда стоит использовать unknown, а когда — any?

Мне нужно понять, как правильно использовать эти два типа и какие преимущества предоставляет unknown по сравнению с any.

5 ответ(ов)

2

Они различаются по семантике.

unknown — это родительский тип для всех других типов. Он представляет собой обычный тип в системе типов.

any означает "отключить проверку типов". Это директива для компилятора.

0

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

  1. any:
    • Позволяет присваивать любое значение.
    • Позволяет вызывать любые методы, так как компилятор не осуществляет проверку типов.
const a: any = 'a'; // OK
const v1: string = a; // OK, так как a имеет тип any
a.trim(); // OK, так как a имеет тип any
  1. unknown:
    • Позволяет присваивать любое значение, но не допускает использования этого значения без предварительной проверки типа.
    • Не позволяет вызывать методы, так как компилятор требует явной проверки типа перед использованием.
const b: unknown = 'b'; // OK, так как можем присваивать любое значение

const v2: string = b; // ERROR, нельзя присвоить unknown в string без проверки
const v3: string = b as string; // OK, явное приведение типа

b.trim(); // ERROR, нельзя вызвать метод на unknown

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

0

Тип any:

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

let myVar: any;

myVar[0];
myVar();
myVar.length;
new myVar();

Во многих случаях такая гибкость компилятора TypeScript оказывается слишком излишней. То есть, он позволяет выполнять операции, которые могут привести к ошибкам во время выполнения.

Тип unknown:

Тип unknown также представляет, как и any, все возможные значения JavaScript. Каждый тип может быть присвоен типу unknown. Таким образом, тип unknown является еще одним универсальным суперклассом системы типов (вместе с any). Однако компилятор TypeScript не будет разрешать любые операции над значениями типа unknown. Более того, тип unknown может быть присвоен только типу any. Пример лучше проиллюстрирует это:

let myVar: unknown;

let myVar1: unknown = myVar;   // Ошибки нет
let myVar2: any = myVar;       // Ошибки нет
let myVar3: boolean = myVar;   // Тип 'unknown' нельзя присвоить типу 'boolean'

// Следующие операции над myVar все вызывают ошибку:
// Объект имеет тип 'unknown'
myVar[0];
myVar();
myVar.length;
new myVar();

Таким образом, по сравнению с типом any, тип unknown обеспечивает большую строгость и безопасность, потому что требует явного приведения типов перед выполнением операций.

0

Я, возможно, запоздал с ответом, но постараюсь внести ясность.

В приведённом вами коде мы имеем дело с двумя переменными:

const canBeAnything: any = 100;
const canNotBeAnything: unknown = 100;

Переменная canBeAnything имеет тип any, что означает, что мы можем использовать любую операцию с ней без ограничений TypeScript. Например, метод .startsWith() можно вызвать без проблем:

canBeAnything.startsWith('10'); // здесь нет ошибки

Однако при работе с переменной типа unknown, как в случае canNotBeAnything, мы сталкиваемся с ограничениями. Если мы попытаемся вызвать тот же самый метод:

canNotBeAnything.startsWith('10'); // ошибка: Свойство 'startsWith' не существует на типе 'unknown'

Это связано с тем, что unknown - это безопасный тип, который требует явного указания типа перед использованием. Чтобы использовать .startsWith(), нам необходимо указать компилятору, что мы уверены, что переменная является строкой:

(canNotBeAnything as string).startsWith('10'); // Успокой компилятор TS, я знаю, что делаю.

Этот подход позволяет избежать ошибок компиляции, но очень важно помнить, что при этом необходимо быть крайне осторожным. Если canNotBeAnything действительно является числом, как в нашем примере, то код приведёт к ошибке во время выполнения:

// Ошибка во время выполнения

Итак, хотя использование приведения типа позволяет избежать проблем на этапе компиляции, это может привести к непредсказуемым ошибкам во время выполнения, если вы не уверены в реальном типе переменной. Важно соблюдать осторожность и по возможности избегать приведения типов без необходимости.

0

В более простых терминах:

  • any позволяет делать всё, что угодно.
  • unknown не позволяет делать ничего, пока вы не проверите тип.

Например:

let a: any;
let b: unknown;

a.anything(); // без ошибки
b.anything(); // ошибка: 'b' имеет тип 'unknown'.

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

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь