1. Exploring the {} Type in TypeScript
Have you ever wondered what type {} actually represents in TypeScript? Is it truly an abbreviation for "any non-nullish value"? Let's delve into this topic further.
When you execute console.log(typeof(d));
, you'll notice that {} is classified as type object
. While this may seem inaccurate, let's first clarify the concept of object
. Lowercase object
denotes any non-primitive value, while uppercase Object
encompasses both primitive and non-primitive values via Object.prototype
.
Attempting to assign a primitive value to object
will result in errors because it only accepts non-primitive values. However, null works since it falls under the object
type, whereas undefined is of type undefined but can still be assigned.
The term "{}" refers to an "Object literal," which encapsulates both object
and Object
. Hence, a wide range of values, including primitives and non-primitives, can be assigned to an object literal, as highlighted on packt.
Under normal circumstances, any value can be assigned to an object literal unless strictNullChecks is enabled. In such cases, null and undefined cannot be assigned, as pointed out by @RobbieSpeed in the comments section.
To explore this further, check out this stackblitz (Note: strictNullChecks is disabled).
2. How to Define an "Empty Object Without Properties"
There are various approaches to achieving this. One method involves instantiating it directly like so: let d = {};
, where the type is automatically inferred without specifying it explicitly.
Another technique is to utilize an interface to define properties when known but make them optional by adding question marks after the property names. This approach not only facilitates use but also enhances intellisense functionality.
For example:
export interface User {
name?: string;
email?: string;
}
let user: User = {};
user.name = "Joe";
user.email = "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="c8a2a7ad88a0a7bca5a9a1a4e6aba7a5">[email protected]</a>";
If you have more questions or need further clarification, don't hesitate to ask!
Ps: For additional insights on objects, refer to 2ality.
Update #1
In response to Paddokt's comment, if you aim to type an object as either empty or containing specific properties, the previous example won't suffice. A different approach is necessary for this scenario.
To limit the variable to either an empty object or an object with specific properties, consider wrapping the object inside another object, as demonstrated below:
export interface optUser {
user?: User;
}
export interface User {
name: string;
email: string;
}
let optuser: optUser = {};
optuser.user = {
name: "Joe",
email: "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="761c1913361e19021b171f1a5815191b">[email protected]</a>"
}
This approach allows the variable to be either an empty object or an object containing a user with mandatory name and email fields.
Note:
Keep in mind that optuser.user = {};
won't function as expected. The optuser variable must either contain a user object or remain empty, as the User itself cannot be an empty object within this context.