TypeScript's object type represents any value that does not have any of the above types. Here I'm declaring a local variable called obj that is of type object. If I now try to assign a value of a primitive type to obj I get a type error every single time.
For example, in line 14 the type checker tells me that type symbol is not assignable to type object, because, again, symbol is a primitive type and object describes all non-primitive types. On the other hand, if I assign a value of a complex type such as an empty object, or an empty array, or a function, the assignment expression type checks just fine.
Therefore, we get an error if we try to pass anything else. This is really helpful because otherwise we would have gotten this error at runtime. Perhaps confusingly TypeScript defines another type called object, which is spelled with an uppercase O.
If I now remove the object type annotation and type obj. again I no longer get any auto completion. The obj variable is inferred to be of the empty object type, a type that represents anything that doesn't have any members on its own. This is why the TypeScript language server doesn't offer any auto completion suggestions here.
As you can see in line two, however, the call to the hasOwnProperty method is still type correct, because of course obj is an object and has access to the hasOwnProperty method. At the same time, you cannot add new properties to an object that has the empty object type.
If you wanted to allow such assignments you could add an explicit string index signature via a type annotation. In that case both the method call in line two, and the property assignment in line three, would be type correct. Finally, another solution could have been to type the entire object as any, in which case the compiler would allow, well, anything.