TypeScript 3.x: доступ к свойствам неизвестного типа - PullRequest
0 голосов
/ 21 января 2020

Я прочитал из документации TypeScript, что вы не можете получить доступ к свойствам неизвестного типа:

// No property accesses, element accesses, or function calls

function f11(x: unknown) {
    x.foo;  // Error
    x[5];  // Error
    x();  // Error
    new x();  // Error
}

Но я не понимаю, почему? Если я могу присвоить каждое значение, включая объект, почему я не могу получить доступ к свойствам?

Я сражаюсь по следующему сценарию: у меня есть объект типа any, и я передаю его Object.entries метод, а затем вызов forEach.

Поскольку он имеет тип any, аргумент вызова forEach будет массивом с первым элементом типа string, а вторым с типом unknown.

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

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

const obj: any = {
  val1: "someval",
  val2: {
    some: "some",
    object: "object",
  },
};
Object.entries(obj).forEach(el => {
  if (el[1].some) {
    console.log(el);
  }
});

error preview

Это также может просто Я полагаю, неправильные вводы для метода Object.entries, но я все же хотел бы объяснить, почему я не могу получить доступ к свойствам типа unknown.

Итак, в качестве резюме мои вопросы:

  1. Почему я не могу получить доступ к свойствам неизвестного типа, даже если ты Неизвестный тип gh может быть объектом?
  2. Я думаю, что есть причина для вышеуказанного вопроса, но не должен Object.entries возвращать массив с элементом nr. 0 типа строка и номер элемента 1 типа любой?

Ответы [ 2 ]

1 голос
/ 21 января 2020

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

unknown отличается. unknown является противоположностью any в этом отношении. Это представляет типобезопасную версию any, в которой говорится: «Я не буду притворяться, что я все подхожу, потому что я этого не делаю». Так что unknown требует дополнительного приведения к нужному типу, чтобы работать (потому что он не обладает какими-либо собственными свойствами).

Теперь к актуальному вопросу. Почему Object.entries использует unknown вместо any? Поскольку безопаснее сказать «приведите это неизвестное значение к тому, что вам нужно перед использованием, Я не буду считать , что я знаю что-либо об этом типе», чем «Я не знаю, какой это тип , но Я предполагаю , что он обладает всеми возможными свойствами всех возможных типов ".

0 голосов
/ 21 января 2020

Определение Object.entries(...) (взято из GitHub ):

entries<T>(o: { [s: string]: T } | ArrayLike<T>): [string, T][];

Поскольку вы явно определили obj как any, вызов Object.entries возвращает

[string, unknown][]

Вы можете просто удалить : any при объявлении obj, и TypeScript выведет его тип из определения.

В этом случае вызов Object.entries вернет:

[string, string | { some: string; object string; }][]

Чтобы ответить на ваши вопросы:

Почему я не могу получить доступ к свойствам типа unknown?

Компилятор пытается избежать ошибок времени выполнения проверяя во время компиляции. Если вы действительно знаете, что делаете, вы всегда можете привести unknown к any. Например:

const value:any = el[1];

Я думаю, что есть причина для вышеуказанного вопроса, но не должен Object.entries возвращать массив с элементом nr. 0 типа строка и номер элемента 1 типа any?

На самом деле возвращает [string, unknown][].

...