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.
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.
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()someconst 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")
}
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
You can also use lodash for checking the object
if(_.isEmpty(this.brand)){
console.log("brand is empty")
}
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;
}
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).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');
}
JSON.stringify(this.brand) === '{}'
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;
})();
};
return condition ? true : some_code is the same as return condition || some_code.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
Object.values(this.brand).some(b => b != null);
{"foo": null} is not an empty object.