108

Trying to figure out the difference between these 2 types in TypeScript:

foo: object

and

bar: {}

and type: Object ?


Example: trying to assign an object to the variable that suppose to handle headers information for a request:

headers: object;

Results in an error:

Type 'object' is not assignable to '{ [key: string]: string }`.

The same condition passes if using headers: {}, which leads to conclusion that {} has some slightly less tight requirements.

0leg
  • 13,464
  • 16
  • 70
  • 94
  • I wonder if there is any, because there does not appear to be. – H.B. Mar 24 '18 at 12:57
  • Under some circumstances TypeScript would trigger an error for one of those. So there might be some. – 0leg Mar 24 '18 at 13:05
  • Well, they are assignable to each other, so please add any such error cases you are aware of to the question. – H.B. Mar 24 '18 at 13:07

2 Answers2

130

TypeScript has three confusing types: Object, {} and object.

You can assign null and undefined to all three types if strictNullChecks compiler option is disabled otherwise the compile error occurs.

Object

Contains stuff (like toString(), hasOwnProperty()) that is present in all JavaScript objects. Any value (primitive, non-primitive) can be assigned to Object type.

{}

{} is an empty object. It is pretty much the same as Object in runtime but different in compile time. In compile time {} doesn't have Object's members and Object has more strict behavior (see the @golmschenk's comment).

object

object was introduced in TypeScript 2.2. It is any non-primitive type. You can't assign to it any primitive type like bool, number, string, symbol.

Thus, if you will try this:

var strictTypeHeaders: { [key: string]: string } = {}; // non-primitive type
var header: object = {};
header = strictTypeHeaders; // its OK
strictTypeHeaders = header; // causes error "Type 'object' is not assignable to type '{ [key: string]: string }`"

you will get the compile error on the last line. This happens because { [key: string]: string } type is more specific than object type. There is no any error on header = strictTypeHeaders since both types are non-primitive and object is more common type than { [key: string]: string }

Inigo
  • 12,186
  • 5
  • 41
  • 70
AlbertK
  • 11,841
  • 5
  • 40
  • 36
  • 8
    Please don't say "*Any object (primitive, non-primitive, null and etc)*" but "any *value*". A primitive is not an object. – Bergi Mar 24 '18 at 14:07
  • 2
    Good answer. Would be great to add the reference urls (if any). – 0leg Mar 24 '18 at 17:25
  • In TS if a function parameter is of type: `{ }`, I cannot call that function with a value of `null`.. Seems to contradict above. – ttugates Sep 13 '19 at 16:10
  • 6
    `Object` and `{}` are not quite the same. Built-in methods have pre-defined enforced types for `Object` but not for `{}`. So `let x: {} = {toString() { return 2 }}` will run, but `let x: Object = {toString() { return 2 }}` will result in an error (because `toString` requires returning a string for `Object` but not for `{}`). – golmschenk Oct 14 '21 at 14:03
79

The following example shows how different types of object behave differently:

var o: object;
o = { prop: 0 }; // OK
o = []; // OK
o = 42; // Error
o = "string"; // Error
o = false; // Error
o = null; // Error
o = undefined; // Error

var p: {}; // or Object
p = { prop: 0 }; // OK
p = []; // OK
p = 42; // OK
p = "string"; // OK
p = false; // OK
p = null; // Error
p = undefined; // Error

var q: { [key: string]: any };
q = { prop: 0 }; // OK
q = []; // OK
q = 42; // Error
q = "string"; // Error
q = false; // Error
q = null; // Error
q = undefined; // Error

var r: { [key: string]: string };
r = { prop: 'string' }; // OK
r = { prop: 0 }; // Error
r = []; // Error
r = 42; // Error
r = "string"; // Error
r = false; // Error
r = null; // Error
r = undefined; // Error

With that we can tell:

  • {} which is the same as type Object is the least specific. You can assign objects, arrays and primitives to it.
  • object is more specific and is similar to { [key: string]: any }. You can assign objects and arrays to it, but not primitives.
  • { [key: string]: string } is the most specific, that doesn't allow any primitive types, arrays or objects with a non-string value to be assigned to it.

Link to TypeScript playground

tanguy_k
  • 11,307
  • 6
  • 54
  • 58
orad
  • 15,272
  • 23
  • 77
  • 113