Files
people_manager/src/models/mutation-proxy.ts
T
2026-06-20 18:56:35 -04:00

62 lines
1.9 KiB
TypeScript

import { clonePlain } from './clone-plain';
export class MutationProxy<T extends object> {
private readonly getOriginal: () => T;
private readonly getMutated: () => Partial<T>;
constructor(
getOriginal: () => T,
getMutated: () => Partial<T>,
) {
this.getOriginal = getOriginal;
this.getMutated = getMutated;
}
create(): T {
return new Proxy({} as T, {
get: (_target, prop: string | symbol) => {
if (typeof prop !== 'string') {
return undefined;
}
const key = prop as keyof T;
const mutated = this.getMutated();
const original = this.getOriginal();
return key in mutated ? mutated[key] : original[key];
},
set: (_target, prop: string | symbol, value: unknown) => {
if (typeof prop === 'string') {
const key = prop as keyof T;
(this.getMutated() as Record<keyof T, unknown>)[key] = clonePlain(value);
}
return true;
},
has: (_target, prop: string | symbol) => {
if (typeof prop !== 'string') {
return false;
}
const mutated = this.getMutated();
const original = this.getOriginal();
return prop in mutated || prop in original;
},
ownKeys: () => {
const mutated = this.getMutated();
const original = this.getOriginal();
return Array.from(new Set([
...Reflect.ownKeys(original),
...Reflect.ownKeys(mutated),
]));
},
getOwnPropertyDescriptor: () => ({
enumerable: true,
configurable: true,
}),
});
}
}