Skip to content

Instantly share code, notes, and snippets.

@adityacodepublic
Created March 2, 2025 10:03
Show Gist options
  • Save adityacodepublic/2cdba051e5b706ef2c82dca31c5eadd8 to your computer and use it in GitHub Desktop.
Save adityacodepublic/2cdba051e5b706ef2c82dca31c5eadd8 to your computer and use it in GitHub Desktop.

Some utils

const isDateObject = (value: unknown): value is Date => value instanceof Date;

const isNullOrUndefined = (value: unknown): value is null | undefined =>
  value == null;

const isObjectType = (value: unknown): value is object =>
  typeof value === "object";

const isObject = <T extends object>(value: unknown): value is T =>
  !isNullOrUndefined(value) &&
  !Array.isArray(value) &&
  isObjectType(value) &&
  !isDateObject(value);

const isEmpty = (value: any): boolean => {
  return (
    value === null ||
    value === undefined ||
    value === "" ||
    (Array.isArray(value) && value.length === 0) ||
    (typeof value === "object" &&
      value !== null &&
      Object.getPrototypeOf(value) === Object.prototype &&
      Object.keys(value).length === 0)
  );
};

type EmptyObject = { [K in string | number]: never };
const isPlainObjects = (value: unknown): value is EmptyObject =>
  isObject(value) && !Object.keys(value).length;

previous

function removeEmptyValues<T extends Record<string, any>>(
  values: T
): Partial<T> {
  const result: Partial<T> = {};
  for (const key in values) {
    const value = values[key];
    if ([null, undefined, "", [], {}].includes(value)) {
      continue;
    }

    if (Array.isArray(value)) {
      const newArray = value.map((item: any) => {
        if (typeof item === "object") {
          return removeEmptyValues(item);
        }
        return item;
      });
      result[key] = newArray.filter((item: any) => item !== null);
    } else if (typeof value === "object") {
      result[key] = removeEmptyValues(value) as any;
    } else {
      result[key] = value;
    }
  }

  return result;
}

remove '', null, empty [], {}

const isPlainObject = (value: any): boolean =>
  Object.prototype.toString.call(value) === "[object Object]";

// removes '', null, empty [], {} 
const cleanValue = (data: any): any => {
  // Remove empty strings, null or undefined
  if (typeof data === "string") {
    return data.trim() === "" ? undefined : data;
  }
  if (data === null || data === undefined) return undefined;

  // Process arrays
  if (Array.isArray(data)) {
    const cleaned = data.map(cleanValue).filter(item => item !== undefined);
    return cleaned.length ? cleaned : undefined;
  }

  // Process plain objects only
  if (typeof data === "object" && isPlainObject(data)) {
    const cleanedObj = Object.entries(data).reduce((acc, [key, value]) => {
      const cleanedVal = cleanValue(value);
      if (cleanedVal !== undefined) acc[key] = cleanedVal;
      return acc;
    }, {} as Record<string, any>);
    return Object.keys(cleanedObj).length ? cleanedObj : undefined;
  }

  // Leave other types (Date, RegExp, functions, etc.) untouched
  return data;
};

replace '', null, empty {} ------> with undefined

/**
 * Replaces with undefined.
 * Remove empty strings '', null, empty objects.
 * Keeps empty arrays.
 */
const cleanValueReplace = (data: any): any => {
  // Remove empty strings. can remove null, but kept it.
  if (typeof data === "string") {
    return data.trim() === "" ? undefined : data;
  }
  if (data === null || data === undefined) return undefined;

  // Process arrays
  if (Array.isArray(data)) {
    const cleaned = data.map(cleanValue).filter((item) => item !== undefined);
    return cleaned;
  }

  // Process plain objects only
  if (typeof data === "object" && isPlainObject(data)) {
    const cleanedObj = Object.entries(data).reduce(
      (acc, [key, value]) => {
        const cleanedVal = cleanValue(value);
        acc[key] = cleanedVal;
        return acc;
      },
      {} as Record<string, any>
    );
    return Object.keys(cleanedObj).length ? cleanedObj : undefined;
  }

  // Leave other types null, object(Date, RegExp, functions, etc.) untouched
  return data;
};
const input = {
  strings: "yes",
  numbers: 2,
  nulls: null,
  booleans: false,
  undefineds: undefined,
  dates: new Date(),
  symbols: Symbol("foo"),
  regexs: new RegExp(/abc/),
  errors: new Error(),
  objects: {
    name: "",
    hi: ["", ""],
    so: "",
    sweet: [{}, { jo: ["", ""], names: { name: "" } }],
  },
  emptyObject: {},
  emptyArray: [],
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment