3

As reference Remove blank attributes from an Object in Javascript, how to make it Typescript compatible?

JS function (nested objects | ES10):

function removeEmpty(obj) {
  return Object.fromEntries(
    Object.entries(obj)
      .filter(([_, v]) => v != null)
      .map(([k, v]) => [k, v === Object(v) ? removeEmpty(v) : v])
  );
}

I've tried with Exclude<T, null> but it doesn't works with nested objects and I think it's not the correct utility to use.

Note that the returned type should remove null type(s) but keeps undefined.

Example/Expected behaviour:

type TestType = {
  a?: {
    b?: {
      c: string;
    } | null;
    z?: {
      x: string;
    };
  } | null;
};

const testObj: TestType = {
  a: {
    b: null,
    z: { x: 'Hi' }
  }
};

const resultObj = removeEmpty(testObj);

Where resultObj type is similar to:

type ResultTestTypeExample = {
  a?: {
    b?: {
      c: string;
    };
    z?: {
      x: string;
    };
  };
};

2 Answers 2

6

Does this work for you?

type ExpandRecursively<T> = T extends object
  ? T extends infer O ? { [K in keyof O]: ExpandRecursively<O[K]> } : never
  : T;

type RemoveNull<T> = ExpandRecursively<{ [K in keyof T]: Exclude<RemoveNull<T[K]>, null> }>

Usage:

function removeEmpty<T extends object>(obj: T): RemoveNull<T> {
  return Object.fromEntries(
    Object.entries(obj)
      .filter(([_, v]) => v != null)
      .map(([k, v]) => [k, v === Object(v) ? removeEmpty(v) : v])
  ) as RemoveNull<T>
}

Playground

Sign up to request clarification or add additional context in comments.

2 Comments

I get this error:
No overload matches this call. Overload 1 of 2, '(o: { [s: string]: unknown; } | ArrayLike<unknown>): [string, unknown][]', gave the following error. Argument of type 'T' is not assignable to parameter of type '{ [s: string]: unknown; } | ArrayLike<unknown>'. Type 'T' is not assignable to type 'ArrayLike<unknown>'. Overload 2 of 2, '(o: {}): [string, any][]', gave the following error. Argument of type 'T' is not assignable to parameter of type '{}'.ts(2769)
0
export function removeNull<T extends object>(obj: T | any) {
  Object.keys(obj).forEach(k => {
    const key = k as keyof T
    if (obj[key] && typeof obj[key] === 'object') removeNull(obj[key])
    else if (obj[key] == null) delete obj[key]
  })
  return obj
}

You can remove null elements with the code above. You can also give your type and it will remove all nested objects properties

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.