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 :-)