'Любой' против 'Объекта'


210

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

interface Blablabla {

   field: Object;

}

В чем преимущество использования Objectпротив any, как в:

interface Blablabla {

  field: any;

}

Ответы:


202

Objectявляется более строгим, чем any. Например:

let a: any;
let b: Object;

a.nomethod(); // Transpiles just fine
b.nomethod(); // Error: Property 'nomethod' does not exist on type 'Object'.

У Objectкласса нет nomethod()функции, поэтому транспортер выдаст ошибку, сообщающую вам именно это. Если вы используете anyвместо этого, вы в основном говорите транспортнику, что все идет, вы не предоставляете никакой информации о том, что хранится a- это может быть что угодно! И поэтому транспортер позволит вам делать все, что вы хотите с чем-то определенным какany .

Короче говоря

  • any может быть любым (вы можете вызвать любой метод и т. д. без ошибок компиляции)
  • Objectвыставляет функции и свойства, определенные в Objectклассе.

285

Немного стар, но не помешает добавить некоторые заметки.

Когда ты пишешь что-то вроде этого

let a: any;
let b: Object;
let c: {};
  • У a нет интерфейса, это может быть что угодно, компилятор ничего не знает о его членах, поэтому при доступе / назначении как для него, так и для его членов проверка типов не выполняется. По сути, вы говорите компилятору: « Отойди, я знаю, что делаю, так что просто поверь мне »;
  • b имеет интерфейс Object, поэтому ТОЛЬКО члены, определенные в этом интерфейсе, доступны для b . Это все еще JavaScript, поэтому все расширяет Object;
  • c расширяет Object, как и все остальное в TypeScript, но не добавляет членов. Поскольку совместимость типов в TypeScript основана на структурном подтипировании, а не на номинальном подтипировании, c оказывается таким же, как b, потому что у них одинаковый интерфейс: интерфейс Object.

И поэтому

a.doSomething(); // Ok: the compiler trusts you on that
b.doSomething(); // Error: Object has no doSomething member
c.doSomething(); // Error: c neither has doSomething nor inherits it from Object

и почему

a.toString(); // Ok: whatever, dude, have it your way
b.toString(); // Ok: toString is defined in Object
c.toString(); // Ok: c inherits toString from Object

Так Objectи {}есть эквиваленты в TypeScript.

Если вы объявите функции, подобные этим

function fa(param: any): void {}
function fb(param: Object): void {}

с намерением принять что-либо для параметра (возможно, вы собираетесь проверять типы во время выполнения, чтобы решить, что с ним делать), помните, что

  • внутри fa компилятор позволит вам делать что угодно с param ;
  • внутри fb компилятор будет позволять вам ссылаться только на члены Object .

Однако стоит отметить, что если предполагается , что param принимает несколько известных типов, лучшим подходом является объявление его с использованием типов объединения, как в

function fc(param: string|number): void {}

Очевидно, что правила наследования ОО по-прежнему применяются, поэтому, если вы хотите принимать экземпляры производных классов и обрабатывать их на основе их базового типа, как в

interface IPerson {
    gender: string;
}

class Person implements IPerson {
    gender: string;
}

class Teacher extends Person {}

function func(person: IPerson): void {
    console.log(person.gender);
}

func(new Person());     // Ok
func(new Teacher());    // Ok
func({gender: 'male'}); // Ok
func({name: 'male'});   // Error: no gender..

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

ОБНОВИТЬ:

Машинопись 2.2 добавлен objectтип, который определяет , что значение является непримитивным: (т.е. не number, string, boolean, symbol, undefined, или null).

Рассмотрим функции, определенные как:

function b(x: Object) {}
function c(x: {}) {}
function d(x: object) {}

xбудет иметь одинаковые доступные свойства во всех этих функциях, но это ошибка типа для вызова dс примитивом:

b("foo"); //Okay
c("foo"); //Okay
d("foo"); //Error: "foo" is a primitive

2
Кто-нибудь знает, почему они решили добавить, {}если они уже были Object? (или наоборот, в зависимости от того, что наступит раньше) Должна быть небольшая разница, верно?
CletusW

4
{}это обычный способ определения (встроенных) интерфейсов, только в этом случае вы определяете интерфейс без элементов. Небольшая разница хорошо объясняется в ответе: « {}расширяется Object, как и все остальное в TypeScript».
DanielM

7
Я хочу, чтобы вы проголосовали за строку. В общем, когда вы не знаете тип, переходите к anyпроверке типов во время выполнения. Не следует использовать any, вместо того, чтобы использовать объединение типов вы проверяете против: TypeA|InterfaceB|string. Если у вас также есть регистр по умолчанию для неизвестного типа, добавьте {}или Objectв объединение.
ILMTitan

Документы с машинописным шрифтом иногда приводят в замешательство, например, But variables of type Object only allow you to assign any value to them - you can’t call arbitrary methods on them, even ones that actually exist:заставляют меня думать, что даже звонки toStringзапрещены, хотя на самом деле я думаю, что они exist at runtimeхотели сказать после прочтения вашего ответа.
Ольга

24

any что-то специфическое для TypeScript довольно хорошо объясняется ответом alex.

Objectссылается на objectтип JavaScript . Обычно используется как {}или иногда new Object. Большинство вещей в javascript совместимы с типом данных объекта, поскольку они наследуются от него. Но anyон специфичен для TypeScript и совместим со всем в обоих направлениях (не на основе наследования). например:

var foo:Object; 
var bar:any;
var num:number;

foo = num; // Not an error
num = foo; // ERROR 

// Any is compatible both ways 
bar = num;
num = bar;  

1
Ваш ответ довольно расплывчатый и смешанный, Objectи objectэто разные типы в TypeScript.
m93a

@ m93a: Можете ли вы рассказать, в чем разница между TS Objectи objectTS?
Александр Абакумов

4
Это , вероятно, лучший источник, чтобы узнать разницу. Суть в том, что objectэто тип для всего, что не является примитивным, в то время Objectкак это интерфейс, который содержит общие вещи, подобные toStringи такие. Номер 42будет, Objectно не object.
m93a

20

В отличие от .NET, где все типы происходят от «объекта», в TypeScript все типы происходят от «любого». Я просто хотел добавить это сравнение, так как думаю, что оно будет обычным делом, поскольку все больше разработчиков .NET пробуют TypeScript.


16

Объект представляется более конкретным объявлением, чем любой. Из спецификации TypeScript (раздел 3):

Все типы в TypeScript являются подтипами одного верхнего типа, называемого типом Any. Ключевое слово any ссылается на этот тип. Тип Any - это единственный тип, который может представлять любое значение JavaScript без ограничений. Все остальные типы подразделяются на примитивные типы, типы объектов или параметры типов. Эти типы вводят различные статические ограничения на их значения.

Также:

Тип Any используется для представления любого значения JavaScript. Значение типа Any поддерживает те же операции, что и значение в JavaScript, и для операций со значениями Any выполняется минимальная проверка статического типа. В частности, к свойствам любого имени можно получить доступ через любое значение, а любые значения можно вызывать как функции или конструкторы с любым списком аргументов.

Объекты не допускают такой же гибкости.

Например:

var myAny : any;

myAny.Something(); // no problemo

var myObject : Object;

myObject.Something(); // Error: The property 'Something' does not exist on value of type 'Object'.

0

Добавляем к ответу Алекса и упрощаем его:

Объекты более строги в своем использовании и, следовательно, дают программисту больше возможностей для «оценки» времени компиляции и, следовательно, во многих случаях предоставляют больше «возможностей проверки» и могут предотвратить любые утечки, тогда как любой - это более общий термин и много компиляции. следовательно, проверки времени могут быть проигнорированы.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.