Ok so the real question is why we can assign any object into {}. This is more about language design choices. Language is build over structural subtyping compatibility.
Type compatibility in TypeScript is based on structural subtyping. Structural typing is a way of relating types based solely on their members. This is in contrast with nominal typing.
It means we can assign to the more loose type values of its subtypes. In your code {} is widest type of object, we can say its parent type for every object type, in other words every other object type is a subtype of {}. Below is some example checks:
type ISubTypeOfEmptyObj<T> = T extends {} ? true : false
type Check1 = ISubTypeOfEmptyObj<{bar: 2}> // yes it is
type Check2 = ISubTypeOfEmptyObj<{foo: 2, bar: 'a'}> // yes it is
type Check3 = ISubTypeOfEmptyObj<number> // surprisingly that is also true
const a: {} = 1; // no error
What does it proof - fact that you can make instance of {} from a thin air almost (only null and undefined values cannot be members of {}). But also it holds true that after initialization you cannot just set some properties to such value, as the type says there are none. In other words you can make {} from almost anything, but you can use it after only like empty object.
Record<string, any> is more strict type than {}, for example every array type will be assignable to {}, and not assignable to Record<string, any>, the same holds for other types like string or number. Record<string, any> represents all object with any string properties, therefor you can append any string property to the object, as type will hold.