Home > Enterprise >  Remove empty optional properties from object
Remove empty optional properties from object

Time:10-01

I´m trying to clean a typed object from empty optional properties with a helper function, and it all works fine. The problem is that i'm running in strict mode and cant figure out how to solve the strict error i get on the result in the if-statement.

export function removeEmptyOptionalProperties<T>(obj: T extends unknown ? any : any): T {
  const result = {} as T;
  Object.keys((obj)).forEach(prop => {
    if (obj[prop] || obj[prop] === false || obj[prop] === 0 || obj[prop] === Array.isArray) {
    /* Here ---> */  result[prop] = obj[prop] as T;
    }
  });
  return { ...result };
}

Test example:

const testObject = {
      undefinedProp: undefined,
      nullProp: null,
      falseProp: false,
      zeroProp: 0,
      emptyString: '',
      filledString: 'filledString',
      filledObject: {
        filledString: 'filledString',
      },
      filledArray: [
        {
          filledString: 'filledString',
        },
      ],
    };

const result = removeEmptyOptionalProperties(testObject);
console.log('result:', result);

The const result shouldn't have any properties that is: undefined, null or ''. Ive tried to look at the error it generates, but cant figure it out how to solve it. Error: 'Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'unknown'. No index signature with a parameter of type 'string' was found on type 'unknown'.ts(7053) ' https://typescript.tv/errors/#TS7053

As said, this function works, but 'strict' dosen´t like it. So I need a solution so 'strict' likes it. Any ideas?

CodePudding user response:

There are 2 issues in the above code:

  1. Object.keys(obj).forEach doesn't take into account, the type of the keys. All the keys will be of type string. So, you will have to manually cast them to the type keyof T.
  2. In this code, result[prop] = obj[prop] as T, you are converting obj[prop] to type T and assigning to result[prop] which is incorrect because result is of type T and result[prop] is of type T[typeof prop].
export function removeEmptyOptionalProperties<T>(obj: T extends unknown ? any : any): T {
  const result = {} as T;
  Object.keys((obj)).forEach((prop) => {

    const key = prop as keyof T // Address first problem

    if (obj[prop] || obj[prop] === false || obj[prop] === 0 || obj[prop] === Array.isArray) {

        result[key] = obj[prop] as T[typeof key];  // Address second problem

    }
  });
  return { ...result };
}

CodePudding user response:

I think I solved it by making the result as a Record, which means that you can add any properties to that object, then returning it as the type that came in.

Like this:

function removeEmptyOptionalProperties<T>(obj: T extends unknown ? any : any): T {
  /* const result = {} as T; */
  const forLoopResult: Record<string, unknown> = {};
  Object.keys((obj)).forEach(prop => {
    if (obj[prop] || obj[prop] === false || obj[prop] === 0 || obj[prop] === Array.isArray) {
      forLoopResult[prop] = obj[prop];
    }
  });
  const result: unknown = { ...forLoopResult };
  return result as T;
}
  • Related