Skip to content

Instantly share code, notes, and snippets.

@renatoargh
Last active January 5, 2022 20:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save renatoargh/928ef8d80d2c886f22c1fc244dd2cacf to your computer and use it in GitHub Desktop.
Save renatoargh/928ef8d80d2c886f22c1fc244dd2cacf to your computer and use it in GitHub Desktop.
import { isUndefined } from "lodash";
export abstract class Cloneable<T> {
public clone(newValues: Partial<T> = {}): T {
const clone = new (this.constructor as new () => T)();
const newValuesWithNestedClones = Object.getOwnPropertyNames(clone)
.reduce((partial, propertyName) => {
const property = Object.getOwnPropertyDescriptor(clone, propertyName) as PropertyDescriptor;
const isCloneable = property.value instanceof Cloneable;
const isNotProvided = isUndefined(
Object.getOwnPropertyDescriptor(partial, propertyName),
);
if (isCloneable && isNotProvided) {
// tslint:disable-next-line:no-unsafe-any
partial[propertyName as keyof T] = property.value.clone();
}
return partial;
}, newValues);
return Object.assign(clone, this, newValuesWithNestedClones);
}
public cloneWith(newValues: Partial<T>): T {
return this.clone(newValues);
}
}
function clone<T>(instance: T): T {
const copy = new (instance.constructor as { new (): T })();
Object.assign(copy, instance);
return copy;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment