declare type Mutable = { -readonly [P in keyof T]: T[P] extends Function ? T[P] : Mutable; }; /** * Shallow clones an object. * * Supports constructor arguments, but requires to annotate them using @f decorator. */ export declare function shallowCloneObject(item: T): T; /** * Class to track object changes and patch mechanism to support updating immutable/frozen objects. * * Use `applyPatch` or `applyAndReturnPatches` for simple use-cases. */ export declare class Patcher { readonly item: T; /** * This is the object with the same shape and origin values as T and SHOULD NOT be changed. * Use `proxy` when you want to apply changes. */ readonly value: T; /** * By updating certain values on this object, `value` property of this class will be changed accordingly, * while only touching and de-referencing the property values that are absolutely necessary. */ readonly proxy: Mutable; /** * As soon as you change values in `value`, this patches object fills up. * * Note: It does not resolve array operations. That means if you have a T shape of * {items: string[]} * and change `value.items.push('another')`, then patches contains `{items: ['another]}`. */ readonly patches: Partial; protected readonly proxies: Map; constructor(item: T); protected getArrayProxy(originalArray: any[], dereferenceArray: () => any[]): never[]; protected getProxy(incomingPath: string, originalItem: any, dereferenceOriginalItem: () => object): any; } /** * This function enables you to track changes made to an object and return only the difference. * The difference in the format of a dot-path object allows you to efficiency save or transport changes. */ export declare function applyAndReturnPatches(item: T, patch: (item: Mutable) => void): Partial; /** * Applies patches to a (readonly) object while not touching the original object * and returns the cloned object while keeping unchanged reference intact. * * Allows to modify a given object partially and keeps references * that weren't updated untouched. This is very useful when working * with state management systems or dirty checking algorithms. * * Returns always a new object, but leaves (deep) property references * intact when they haven't changed (using the `patcher` modifier). * * If a deep property has changed (like children.deep.title), then * children, and children.deep will have a new reference/instance. * `children.another` on other other side is not changed and would not * have a new reference. * * This function is very handy when dealing with state management where * you want to make sure that references only change when you really have changed * either its value or some (nested) children values. Normally you have to use * the spread syntax (...) to quickly create a copy of the state and re-assign * only a subset of properties. Like so * * return {...state, loggedIn: true}; * * This becomes quickly unused when you have a more complex state. (more complex states * are generally not recommended exactly because of that reason) * However, patch method enables you to work with unlimited complex stores * while having a very easy and convenient way of updating only certain parts of it. * * When given `item` (or a children object) has constructor arguments, * then it's required to annotate them using the @f decorator. * * It's allowed to pass a freezed (Object.freeze) item (and that's a main purpose of this function). * * @example * ```typescript * * class Sub { * title: string = ''; * sub: Sub = new Sub; * } * * class State { * sub: Sub = new Sub(); * otherSub: Sub = new Sub(); * title: string = ''; * } * * const state = new State; * const newState = patchState(state, (state) => { * state.sub.title = 'another-value'; * }); * state === newState //false, always the case * state.sub === newState.sub //false, because we changed it * state.otherSub === newState.otherSub //true, the same since unchanged * * const newState2 = patchState(state, (state) => { * state.otherSub.sub.title = 'another-value'; * }); * state === newState2 //false, always the case * state.sub === newState2.sub //true, because we haven't changed it * state.otherSub === newState2.otherSub //false, since we deeply changed it * ``` */ export declare function applyPatch(item: T, patch: (item: Mutable) => void): T; export {};