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

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

interface Blablabla {

   field: Object;

}

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

interface Blablabla {

  field: any;

}

Ответ 1

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 вместо этого вы в основном говорите transpiler, что все идет, вы не предоставляете никакой информации о том, что хранится в - это может быть что угодно! И поэтому транспортер позволит вам делать все, что вы хотите с чем-то определенным как any.

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

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

Ответ 2

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

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

var a: any;
var b: Object;
var c: {};
  • a не имеет интерфейса, это может быть что угодно, компилятор ничего не знает о своих членах, поэтому минимальная проверка типов выполняется при доступе/назначении как себе, так и его членам. В принципе, вы говорите компилятору "отступить, я знаю, что я делаю, поэтому просто доверяйте мне";
  • b имеет интерфейс Object, поэтому ТОЛЬКО члены, определенные в этом интерфейсе, доступны для b. Он все еще JavaScript, поэтому все расширяет Object;
  • c расширяет объект, как и все остальное в 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 {}

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

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

Итак, в основном, когда вы не знаете тип, перейдите в любой и выполните проверку типа времени выполнения.

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

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..

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

UPDATE:

Typescript 2.2 добавлен тип Object, который указывает, что значение является непримитивным: (т.е. не a 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

Ответ 3

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

Object относится к типу JavaScript Object. Обычно используется как {} или иногда 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;  

Ответ 4

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

Ответ 5

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

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

также:

Любой тип используется для представления любого значения JavaScript. Значение Любой тип поддерживает те же операции, что и значение в 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'.

Ответ 6

Добавление в Alex ответа и его упрощение:

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

Ответ 7

Помните, что вы почти никогда не должны использовать типы Number, String, Boolean или Object в соответствии с документацией Typescript

Эти типы относятся к не примитивным коробочным объектам, которые почти никогда не используются надлежащим образом в коде JavaScript.

Ответ 8

попробуйте следующее:

private a: Object<any> = {};

constructor() {
    a.name = "foo";
}