Open azu opened 6 years ago
Copy
/**
*
* K is type of a key
* T[K] is type of its value
*/
export type PartialMap<T> = { [K in keyof T]?: (prev: T[K]) => T[K] };
/**
* Constructor type
*/
export type Constructor<T = {}> = new (...args: any[]) => T;
/**
* Copyable can copy current instance and map new value
*/
export interface CopyableMethod<T> {
copy(partial: Partial<T>): T;
mapCopy(partial: PartialMap<T>): T;
}
export type Properties<T> = { [K in keyof T]: T[K] };
/**
* Mixin Copyable to the BaseClass
* @param BaseClass
* @returns Copyable class
* @example
*
* class A extends Copyable<Entity<EntityIdentifier>>{}
*/
export const Copyable = <T extends Constructor>(BaseClass: T) => {
return class extends BaseClass {
/**
* Return partial change of this object
*
* e.g)
* `new Person("jack", 2).copy({age: 10})` is `new Person("jack", 10)`
*
*/
copy(partial: Partial<Properties<this>>): this {
const Prototype = Object.getPrototypeOf(this);
const newInstance = Object.create(Prototype);
return Object.assign(newInstance, partial);
}
/**
* Return partial change of this object by using functions
*
* e.g)
* `new Person("jack", 10).mapCopy({age: prev => prev+1})` is `new Person("jack", 11)`
*
* @param {PartialMap<T>} partial
* @returns {T}
*/
mapCopy(partial: PartialMap<this>): this {
const Prototype = Object.getPrototypeOf(this);
const newInstance = Object.create(Prototype);
const oldInstance: { [index: string]: any } = this;
for (const key of Object.keys(this)) {
if (key in partial) {
newInstance[key] = (partial as any)[key](oldInstance[key]);
} else {
newInstance[key] = oldInstance[key];
}
}
return newInstance;
}
};
};
Note: mixin should support ValueObject
class AbstractBookmark extends ValueObject<BookmarkProps>{}
export class Bookmark extends Copyable(AbstractBookmark) {
}