Unfra
Unfra

Reputation: 1283

Check if specific object is empty in typescript

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

Answers (14)

simPod
simPod

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

Tetarchus
Tetarchus

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:

  • Checking whether the passed argument is an object
  • Checking that it's not null (typeof x === 'object' returns true for null)
  • Running any other checks that suit your use cases (depending on whether you care about null or undefined values within the object) - in this case the 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

DeepSea
DeepSea

Reputation: 3232

Use Object.keys(obj).length to check if it is empty.

Output : 3

Source: Object.keys()

Upvotes: 220

kaznovac
kaznovac

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

lukas_o
lukas_o

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

Sareesh Krishnan
Sareesh Krishnan

Reputation: 720

JSON.stringify(this.brand) === '{}'

Upvotes: 1

Er.Kaudam
Er.Kaudam

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

Manoj Kalluri
Manoj Kalluri

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

Orelsanpls
Orelsanpls

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

adiga
adiga

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:

  • Get all the values of the object in an array using Object.values()
  • Check if at least one of has value using 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

Narek Tootikian
Narek Tootikian

Reputation: 1443

If you build ECMA 7+ can try Object.entries(obj).length === 0 && obj.constructor === Object

Upvotes: 0

jmuhire
jmuhire

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

regnar
regnar

Reputation: 519

Object.values(this.brand).some(b => b != null);

Upvotes: -1

Aravind
Aravind

Reputation: 41581

You can also use lodash for checking the object

if(_.isEmpty(this.brand)){
    console.log("brand is empty")
}

Upvotes: 11

Related Questions