Reputation: 1283
How to check if an object is empty?
ex:
private brand: Brand = new Brand();
I tried:
if (this.brand) {
console.log('is empty');
}
not working.
Upvotes: 127
Views: 266271
Reputation: 13506
Since I'm using type-fest's EmptyObject
, I went with this typeguard:
is.emptyObject(val)
https://github.com/sindresorhus/is#emptyobjectvalue
Returns true if the value is an Object and Object.keys(value).length is 0.
Please note that Object.keys returns only own enumerable properties. Hence something like this can happen:
const object1 = {};
Object.defineProperty(object1, 'property1', {
value: 42,
writable: true,
enumerable: false,
configurable: true
});
is.emptyObject(object1);
//=> true
Upvotes: 0
Reputation: 401
If you want a fully type-safe answer for this, that allows you to tell tsc
that an object is, or is not empty when narrowing a union type, you can create a type guard utility function using one of the above answers as suits your needs:
const isEmpty = (obj: unknown): obj is Record<never, never> =>
typeof obj === 'object' && obj !== null && Object.keys(obj).length === 0;
This allows you to have a type that could be an object with keys or an empty object (or any other type for that matter), and tell tsc
that it is (or is not) and empty object by:
null
(typeof x === 'object'
returns true
for null)Object.keys().length
method.You can then use this with:
const unknownType: {prop: number} | Record<never, never> =
functionThatCouldReturnAnEmptyObjectOrNot();
// Type guard returns 'true' and 'definitelyEmpty' will be inferred as an empty object
const definitelyEmpty = isEmpty(unknownType) ? unknownType : {};
// Type guard returns 'false', reversed with the '!', and 'definitelyNotEmpty'
// will be inferred as an object of type {prop: number}
const definitelyNotEmpty = !isEmpty(unknownType) ? unknownType : {prop: 1};
// Not using a type guard, tsc will still infer 'notNarrowed' as
// ({prop: number} | Record<never, never>), meaning that using it where an empty
// object (or not empty object) is required will cause a warning.
const notNarrowed = Object.keys(unknownType).length === 0 ? unknownType : {};
Some other potentially useful notes:
Record<never, never>
means an empty object ({}
){}
as a type annotation (e.g: const empty: {} = {}
) actually means 'any non-nullish value' so is only just above any
in terms of type safety, and will allow most other values (const empty: {} = 3
would be valid).Upvotes: 3
Reputation: 3232
Use Object.keys(obj).length
to check if it is empty.
Output : 3
Source: Object.keys()
Upvotes: 220
Reputation: 1584
This is the fastest construct that I'm aware of, albeit it uses somewhat puzzling for...in
loop that doesn't loop (in my tests it's about 2x faster than Object.keys
)
export function isObjectEmpty(object: Record<string, unknown>): boolean {
for (const property in object) {
// if any enumerable property is found object is not empty
return false;
}
return true;
}
Upvotes: 10
Reputation: 4256
Here is a comparison between the 2 most popular answers, they do have slightly different implications:
let o1 = {}
console.log(JSON.stringify(o1) === '{}')
console.log(Object.keys(o1).length === 0)
// true
// true
let o2 = { p: undefined }
console.log(JSON.stringify(o2) === '{}')
console.log(Object.keys(o2).length === 0)
// true
// false
let o3 = { l: null }
console.log(JSON.stringify(o3) === '{}')
console.log(Object.keys(o3).length === 0)
// false
// false
Upvotes: 20
Reputation: 91
let contacts = {};
if(Object.keys(contacts).length==0){
console.log("contacts is an Empty Object");
}else{
console.log("contacts is Not an Empty Object");
}
Upvotes: 9
Reputation: 1474
Object.keys(myObject).length == 0
A Map obj can be created with empty properties and size might not work . Object might not be equal to empty or undefined
But with above code you can find whether an object is really empty or not
Upvotes: 10
Reputation: 23575
Careful about Object.keys
and Array.some
solutions, in case if your object is not even initialized and worth null
.
Also care that there is no key worthing undefined
.
const objNotInitialized = null;
console.log(Object.keys(objNotInitialized));
You could add an extra check in that case, leading to the final soluce :
function isEmpty(obj) {
return !obj || !Object.keys(obj).some(x => obj[x] !== void 0);
}
console.log(isEmpty({
x: void 0,
}));
console.log(isEmpty(null));
console.log(isEmpty({
key: 'value',
}));
If you can use Object.values
:
function isEmpty(obj) {
return !obj || !Object.values(obj).some(x => x !== void 0);
}
console.log(isEmpty({
x: void 0,
}));
console.log(isEmpty(null));
console.log(isEmpty({
key: 'value',
}));
const obj = {};
// Using Object.keys to loop on the object keys and count them up
if (!Object.keys(obj).length) {
console.log('#1 obj is empty');
}
// What if a key worth undefined ?
const objWithUndefinedKey = {
x: void 0,
};
// Using Object.keys is not enough, we have to check the value behind to remove
// undefined values
if (!Object.keys(objWithUndefinedKey).some(x => objWithUndefinedKey[x] !== void 0)) {
console.log('#2 obj is empty');
}
// Or more elegant using Object.values
if (!Object.values(objWithUndefinedKey).some(x => x !== void 0)) {
console.log('#3 obj is empty');
}
// Alternative is to use for ... in
let empty = true;
for (key in objWithUndefinedKey) {
if (objWithUndefinedKey[key] !== void 0) {
empty = false;
}
}
if (empty) {
console.log('#4 obj is empty');
}
Upvotes: 2
Reputation: 35259
You can use Object.keys
like this:
class Brand { }
const brand = new Brand();
if (Object.keys(brand).length === 0) {
console.log("No properties")
}
If you want to check if the object has at least one non-null, non-undefined property:
Object.values()
some
const hasValues =
(obj) => Object.values(obj).some(v => v !== null && typeof v !== "undefined")
class Brand { }
const brand = new Brand();
if (hasValues(brand)) {
console.log("This won't be logged")
}
brand.name = null;
if (hasValues(brand)) {
console.log("Still no")
}
brand.name = "Nike";
if (hasValues(brand)) {
console.log("This object has some non-null, non-undefined properties")
}
Upvotes: 56
Reputation: 1443
If you build ECMA 7+ can try
Object.entries(obj).length === 0 && obj.constructor === Object
Upvotes: 0
Reputation: 2221
The good approach is to have a short function that you can use everywhere in your app :
export const isEmpty = (obj) => {
return obj === null || undefined
? true
: (() => {
for (const prop in obj) {
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
return false;
}
}
return true;
})();
};
Upvotes: 0