TypeScript '{}' type

1. What is actually {} type in TypeScript? Does it really stand for "any non nullish value" (can't find confirmation in TypeScript documentation)?

If you do console.log(typeof(d)); then you will see that {} is of type object. Except this is not entirely correct but let me explain about object first. First of all object with lowercase o can be any non-primitive value while Object with uppercase O can include any primitive value through Object.prototype.

So if you try to overwrite object with a primitive value it will give errors as it doesn't like primitive values, although null will work as is a object type aswell, undefined on the other hand is of type undefined but this can always be assigned.

Now {} is called "Object literal" this is actually both object and Object. So that is why both primitive and non-primitive values are assignable to an object literal as mentioned on packt.

So normally any value can be assigned to an object literal.

You can check this in the following stackblitz.

2. How should I actually type "empty object without any properties"?

There are probably a couple of ways to do this, the ones I know are you can either instantiate it like you did or do: let d = {}; as the type is automatically determined there is no need to add a type.

The other method is to use an interface to define your properties when they are known but make them all optional by adding question marks behind the property names. This makes it easy to use aswell since all your properties are known and can be found by intellisense aswell.

Example:

export interface User {
    name?: string;
    email?: string;
}

let user: User = {};
user.name = "Joe";
user.email = "[email protected]";

If this didn't answer your question sufficiently, feel free to ask away!

Ps: for more information on objects check out 2ality


The TypeScript FAQ already mentions this:
https://github.com/Microsoft/TypeScript/wiki/FAQ#why-are-all-types-assignable-to-empty-interfaces

The type {} has no properties, booleans have the same thing: no properties.

See the logic now?

One can actually try to look up a property on a boolean/number.

Here's the code that you would expect:

{}.a;
'a' in {};

Which would be undefined and false for the two expressions respectively.

Yet, let's do something stupid, we'll swap it in with a number and a boolean:

0.0.a;
'a' in 0.0;

true.a;
'a' in true;

They still give the same results, there would be no difference.

Thus, they could fit into wherever {} would, since they won't throw, and they will return undefined for all of the required properties.

Now take these:

null.a;
undefined.a;
'a' in null;

And you have runtime errors, thus they cannot mimic an empty object {};


Because of what I gave above... it isn't possible to get an empty object.

The null prototype issue hasn't been solved yet, thus we have no type for this expression: Object.create(null).

Type inference will still result in the same problem:

let x = {};

x is deducted as {}, not helpful.

const x: Record<never, never> = true;

Valid, thus a fail for us.

It seems there is no solution for this.


TypeScript checks that objects have all the properties their type declares. However, TypeScript doesn't generally require that types declare all properties an object has.

For instance, if we declare:

let person: {name: string}; 

we may do

let joe = {name: 'joe', occupation: 'developer'};
person = joe; // just fine: joe has everything a person needs

and likewise, we can do:

let obj: {} = joe; // just fine: joe has everything obj needs

That is, the type {} can indeed be assigned any object, because it doesn't require that object to have any particular properties.

That leaves the puzzling question of how false, a boolean, could possibly pass for an object. The reason is:

For purposes of determining type relationships (section 3.11) and accessing properties (section 4.13), the Boolean primitive type behaves as an object type with the same properties as the global interface type 'Boolean'.

That is, because EcmaScript will automatically convert a boolean into a Boolean if required, TypeScript allows passing a boolean whenever a Boolean is allowed (and Boolean is allowed because it has all properties {} needs ...)

So yes, it is correct that everything except null and undefined could be put into a variable of type {}. That's by design. {} doesn't require any properties, so any object will do.

How should I actually type "empty object without any properties"?

If you mean to say: This is some object, but I don't need it to have any particular properties (for instance because you won't be accessing any properties, or will be accessing them in a generic way), using {} or object is fine, though object would probably convey your intent more clearly.

If you mean to say: This object will never have any properties ... you can't. TypeScript can not ensure this, because it must interoperate with JavaScript, which allows adding properties to objects at any time:

const empty = {};

// somewhere else
empty['foo'] = 'bar'; // no longer empty :-)

Tags:

Typescript