For some time now, I have been attempting to create a declaration for RecursiveOmit and RecursivePick in cloning methods such as JSON.parse(JSON.stringify(obj, ['myProperty']))
type RecursiveKey<T> = T extends object ? keyof T | RecursiveKey<T[keyof T]> : never;
type RecursivePick<T, K> = {
[P in keyof T]: P extends K ? (T[P] extends object ? RecursivePick<T[P], K> : T[P]) : never
}
type RecursiveOmit<T, K> = {
[P in keyof T]: P extends K ? never : (T[P] extends object ? RecursiveOmit<T[P], K> : T[P])
}
const clone = <T, K extends RecursiveKey<T>>(object: T, whiteListedProperties: K[]): RecursivePick<T, K> => {
return JSON.parse(JSON.stringify(object, whiteListedProperties as (string | number)[]));
}
const cloneWithBlackList = <T, K extends RecursiveKey<T>>(object: T, blackListedProperties: K[]): RecursiveOmit<T, K> => {
return JSON.parse(JSON.stringify(object, (key: string, value: any): any => blackListedProperties.includes(key as K) ? undefined : value));
};
const c = {
a: {
a: 1,
b: 2,
c: 3
},
b: {
a: 1,
b: 2
}
}
const cc = clone(c, ['b']);
cc.b.a = 2 // error a shouldn't exists on cc.b
cc.b.b = 2; // b should exists on cc.b
cc.a.c = 2 // error c shouldn't exists on cc.a
const cb = cloneWithBlackList(c, ['b']);
cb.a.a = 2; // a should exists on cb.a
cb.b.b = 3; // error b shouldn't exists on cb
cb.a.c = 2; // c should exists on cb.a
I've experimented with different variations of this code and explored similar answers from other questions. However, despite several attempts, I have not been able to make it work.
If anyone has any insights on what might be going wrong, please share!