#Type and implementation for adding "" as a possible type/value recursively

5 messages · Page 1 of 1 (latest)

full frost
#

I need to be able to deeply replace all undefined values in a complex object structure with empty string.
I thought it would be good to define the type for it. I asked an LLM and tweaked what it gave back, and I think it's accurate

type AddType<Base, New> = Base extends Array<infer U>
  ? Array<AddType<U, New>> // If Base is an array, recursively apply AddType to its elements
  : Base extends object
  ? { [K in keyof Base]: AddType<Base[K], New> } // If Base is an object, recursively apply AddType to its values
  : Base | New;

I'm writing the implementation of the util now, and I believe it works, but I'm wondering if there is a better way to do it because i have to put in a LOT of casting to make TS accept it, and that feels wrong.

const replaceUndefinedWithEmptyString = <T>(value: T): AddType<T, ""> => {
  if (typeof value === "undefined") {
    return "";
  }
  if (typeof value !== "object") {
    return value;
  }
  if (value === null) {
    return value;
  }
  if (Array.isArray(value)) {
    return value.map(replaceUndefinedWithEmptyString);
  }
  const clone = { ...value } as AddType<T, "">;
  let key: keyof T;
  for (key in clone) {
    if (key in clone) {
      clone[key] = replaceUndefinedWithEmptyString(clone[key]);
    }
  }
  return clone;
};
uneven snow
#

Haven't looked closely, but yeah, almost certainly it's going to involve a lot of casting to make this work.

#

Pretty much whenever you use generic conditional types you're going to be in 'cast to make it work' land

full frost
#

Ah, this also chokes on Date objects

#

I realized I can just use a replacer in JSON.stringify 😛