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;
};