232

I am looking at TypeScript code and noticed that they use:

interface Blablabla {

   field: Object;

}

What is the benefit of using Object vs any, as in:

interface Blablabla {

  field: any;

}
Alexander Abakumov
  • 10,817
  • 10
  • 71
  • 111
Olivier Refalo
  • 46,213
  • 20
  • 84
  • 114

6 Answers6

308

Bit old, but doesn't hurt to add some notes.

When you write something like this

let a: any;
let b: Object;
let c: {};
  • a has no interface, it can be anything, the compiler knows nothing about its members so no type checking is performed when accessing/assigning both to it and its members. Basically, you're telling the compiler to "back off, I know what I'm doing, so just trust me";
  • b has the Object interface, so ONLY the members defined in that interface are available for b. It's still JavaScript, so everything extends Object;
  • c extends Object, like anything else in TypeScript, but adds no members. Since type compatibility in TypeScript is based on structural subtyping, not nominal subtyping, c ends up being the same as b because they have the same interface: the Object interface.

And that's why

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

and why

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

So Object and {} are equivalents in TypeScript.

If you declare functions like these

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

with the intention of accepting anything for param (maybe you're going to check types at run-time to decide what to do with it), remember that

  • inside fa, the compiler will let you do whatever you want with param;
  • inside fb, the compiler will only let you reference Object's members.

It is worth noting, though, that if param is supposed to accept multiple known types, a better approach is to declare it using union types, as in

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

Obviously, OO inheritance rules still apply, so if you want to accept instances of derived classes and treat them based on their base type, as in

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

the base type is the way to do it, not any. But that's OO, out of scope, I just wanted to clarify that any should only be used when you don't know whats coming, and for anything else you should annotate the correct type.

UPDATE:

Typescript 2.2 added an object type, which specifies that a value is a non-primitive: (i.e. not a number, string, boolean, symbol, undefined, or null).

Consider functions defined as:

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

x will have the same available properties within all of these functions, but it's a type error to call d with a primitive:

b("foo"); //Okay
c("foo"); //Okay
d("foo"); //Error: "foo" is a primitive
diegovilar
  • 3,389
  • 1
  • 11
  • 5
  • 2
    Does anybody know *why* they decided to add `{}` then if they already had `Object`? (or vice versa, whichever came first) There's got to be some slight difference, right? – CletusW May 25 '17 at 16:01
  • 4
    `{}` is the normal way to define (inline) interfaces, only that in this case you are defining an interface with no members. The slight difference is well explained in the response: "`{}` extends `Object`, like anything else in TypeScript". – DanielM Jun 29 '17 at 12:32
  • 7
    I want to down vote you for the line _So, basically, when you don't know the type, go with `any` and do run-time type checking._ Don't use `any`, instead use a union of the types you are checking against: `TypeA|InterfaceB|string`. If you also have a default case for an unknown type, add either `{}` or `Object` to the union. – ILMTitan Feb 02 '18 at 18:09
  • Typescript docs are sometimes confusing, for example `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:` made me think that even calling `toString` is not allowed, when in fact I think they meant to say `exist at runtime` after reading you answer. – Olga Aug 30 '18 at 15:53
224

Object is more restrictive than any. For example:

let a: any;
let b: Object;

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

The Object class does not have a nomethod() function, therefore the transpiler will generate an error telling you exactly that. If you use any instead you are basically telling the transpiler that anything goes, you are providing no information about what is stored in a - it can be anything! And therefore the transpiler will allow you to do whatever you want with something defined as any.

So in short

  • any can be anything (you can call any method etc on it without compilation errors)
  • Object exposes the functions and properties defined in the Object class.
Nypan
  • 6,037
  • 3
  • 18
  • 27
25

any is something specific to TypeScript is explained quite well by alex's answer.

Object refers to the JavaScript object type. Commonly used as {} or sometimes new Object. Most things in javascript are compatible with the object data type as they inherit from it. But any is TypeScript specific and compatible with everything in both directions (not inheritance based). e.g. :

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;  
basarat
  • 207,493
  • 46
  • 386
  • 462
  • 1
    Your answer is quite vague and mixes `Object` and `object` which are different types in TypeScript. – m93a Apr 30 '18 at 15:36
  • @m93a: Can you expand on what is the difference between `Object` and `object` in TS? – Alexander Abakumov Jun 18 '18 at 19:22
  • 4
    [This](https://blog.mariusschulz.com/2017/02/24/typescript-2-2-the-object-type#object-vs-object-vs) is probably the best source to learn the difference. The main point is that `object` is a type for everything that is not primitive, while `Object` is an interface that contains common things like `toString` and such. The number `42` would be an `Object` but not an `object`. – m93a Jun 20 '18 at 14:22
22

Contrary to .NET where all types derive from an "object", in TypeScript, all types derive from "any". I just wanted to add this comparison as I think it will be a common one made as more .NET developers give TypeScript a try.

yellowbrickcode
  • 651
  • 6
  • 15
18

Object appears to be a more specific declaration than any. From the TypeScript spec (section 3):

All types in TypeScript are subtypes of a single top type called the Any type. The any keyword references this type. The Any type is the one type that can represent any JavaScript value with no constraints. All other types are categorized as primitive types, object types, or type parameters. These types introduce various static constraints on their values.

Also:

The Any type is used to represent any JavaScript value. A value of the Any type supports the same operations as a value in JavaScript and minimal static type checking is performed for operations on Any values. Specifically, properties of any name can be accessed through an Any value and Any values can be called as functions or constructors with any argument list.

Objects do not allow the same flexibility.

For example:

var myAny : any;

myAny.Something(); // no problemo

var myObject : Object;

myObject.Something(); // Error: The property 'Something' does not exist on value of type 'Object'.
Alex Dresko
  • 4,817
  • 2
  • 35
  • 54
0

Adding to Alex's answer and simplifying it:

Objects are more strict with their use and hence gives the programmer more compile time "evaluation" power and hence in a lot of cases provide more "checking capability" and coould prevent any leaks, whereas any is a more generic term and a lot of compile time checks might hence be ignored.

Krishna Ganeriwal
  • 1,555
  • 15
  • 15