0

I have the following utility method: it removes all the empty keys of a payload object.

Here is the code:

const removeEmptyKeysUtil = (payload: any): any => {
  Object.keys(payload).map(
    (key): any => {
      if (payload && payload[key] === '') {
        delete payload[key];
      }
      return false;
    }
  );
  return payload;
};

export default removeEmptyKeysUtil;

But I get the following eslint error:

Assignment to property of function parameter 'payload'.eslint(no-param-reassign)

It was suggested to me that I use either object destructuring or Object.assign. But I am a little confused on how to do that.

For example, destructuring:

      if (payload && payload[key] === '') {
         const {delete payload[key], ...actualPayload} = payload;
      }
      return false;

But I get this error:

Block-scoped variable 'payload' used before its declaration.

I know, I can disable the rule, but I do not want to do that. I want to properly code that branch

Can you help me a little bit? I don't think I understand those 2 concepts at all. Thank you.

Richard-Degenne
  • 2,892
  • 2
  • 26
  • 43

2 Answers2

0

Lint is warning you to fulfill one of the properties called "immutability".

So when you receive a parameter to use in this function (which is an object) indicates that what you return from that function is a new object with the modifications you want but that this is a new object.

PD: In addition, if you use Typescript and you know what that payload is made of, it would be best if you created an interface with its data rather than assigning any because it can help you select internal properties and avoid errors, as well as the response it will return.

One solution could be this:

const removeEmptyKeysUtil = (payload: any): any =>
  Object.keys(payload)
    .filter(key => payload[key] !== "")
    .reduce((result, key) => ({ ...result, [key]: payload[key] }), {});

export default removeEmptyKeysUtil;
frangaliana
  • 793
  • 8
  • 17
  • What you are suggesting here is returning me the same error for the `result`. I have a simpler solution to your suggestion, which is working correctly, but do you have a solution which doesn't restructured my existing code.. –  Jun 27 '19 at 10:10
  • @DimitrisEfst , I'm sorry to have restructured it, I've corrected a little something that had left me in the middle, I've tried to make it as simple and with as few lines as possible. Could you give us your solution so that we can take a look at it? :) – frangaliana Jun 27 '19 at 10:37
0

I know this answer is probably not exactly what you were looking for. Since your code will perform badly on complicated object I created a quick solution which will give the result you wanted. I hope it helps.

function isEmptyObject(obj) {
  if (!obj || typeof obj !== 'object') return false;
  if (obj.constructor === Array) return obj.length === 0;
  return Object.keys(obj).length === 0 && obj.constructor === Object;
}

function removeEmptyKeysUtil(obj) {
  if (!obj) return {};
  Object.keys(obj).map(key => {
    // Add additional check here for null, undefined, etc..
    if (obj[key] === '') delete obj[key]; 

    if (obj.constructor === Object) {
      obj[key] = removeEmptyKeysUtil(obj[key])
    }

    if (obj.constructor === Array) {
      for (let i = obj.length; i >= 0; i--) {
        obj[i] = removeEmptyKeysUtil(obj[i])
        if (isEmptyObject(obj[i])) {
          obj.splice(i, 1);
        }
      }
    }

    if (isEmptyObject(obj[key])) {
      delete obj[key];
    }
  })
  return obj;
}

const obj = {
  test: '11',
  test1: '1',
  test2: {
    test: '',
    test1: ''
  },
  test3: [
    {
      test: ''
    },
    {
      test: ''
    },
    {
      test: '3'
    },
    {
      test33: {
        test: '1',
        test1: ''
      }
    }
  ]
};

console.log(removeEmptyKeysUtil(obj))
jank
  • 840
  • 4
  • 7