@tsfun/object
Advanced tools
+82
-21
| import { SimpleDeepMerge } from './utils/types'; | ||
| /** | ||
| * Merge two objects of the same interface | ||
| * @param left Object or value to merge | ||
| * @param right Object or value to merge | ||
| * @param resolveConflict Function that resolves property conflict | ||
| * @returns Result of the merge | ||
| */ | ||
| export declare function deepMergeWithPreference<Value>(left: Value, right: Value, resolveConflict: PropertyConflictResolver): Value; | ||
| /** | ||
| * Decides which property should make it to the merged object | ||
| */ | ||
| export interface PropertyConflictResolver { | ||
| /** | ||
| * @param values Pair of conflicting properties | ||
| * @returns Property choice | ||
| */ | ||
| (values: [unknown, unknown]): PropertyPreference; | ||
| } | ||
| /** | ||
| * Choice to be made | ||
| */ | ||
| export declare const enum PropertyPreference { | ||
| /** | ||
| * Choose the left value (`values[0]`) | ||
| */ | ||
| Left = 0, | ||
| /** | ||
| * Choose the right value (`values[1]`) | ||
| */ | ||
| Right = 1 | ||
| } | ||
| /** | ||
| * Merge two objects of the same interface | ||
| * | ||
| * `b` is prioritized for overlapping non-object properties | ||
| * `left` is prioritized for overlapping non-object properties | ||
| * | ||
| * @param a Object or value to merge | ||
| * @param b Object or value to merge | ||
| * @param left Object or value to merge | ||
| * @param right Object or value to merge | ||
| * @returns Result of the merge | ||
| */ | ||
| export declare function deepMergeOverwrite<Value>(a: Value, b: Value): Value; | ||
| export declare function deepMergeOverwrite<Value>(left: Value, right: Value): Value; | ||
| /** | ||
@@ -17,22 +48,52 @@ * Merge two objects | ||
| * | ||
| * @param a Object to merge | ||
| * @param b Object to merge | ||
| * @param left Object to merge | ||
| * @param right Object to merge | ||
| * @param onerror Function to handle should error occurs | ||
| * @returns A merged object of `a` and `b` | ||
| */ | ||
| export declare function deepMergeWithoutCollision<A extends object, B extends object>(a: A, b: B, onerror?: deepMergeWithoutCollision.ErrorProcessor): SimpleDeepMerge<A, B>; | ||
| export declare namespace deepMergeWithoutCollision { | ||
| interface ErrorProcessor { | ||
| (param: ErrorProcessorParam): unknown; | ||
| } | ||
| type ErrorProcessorParam = PropertyCollision; | ||
| const enum ErrorType { | ||
| PropertyCollision = 1 | ||
| } | ||
| interface PropertyCollision { | ||
| type: ErrorType.PropertyCollision; | ||
| objects: [object, object]; | ||
| key: string | symbol; | ||
| values: [unknown, unknown]; | ||
| } | ||
| export declare function deepMergeWithoutCollision<Left extends object, Right extends object>(left: Left, right: Right, onerror?: ErrorProcessor): SimpleDeepMerge<Left, Right>; | ||
| /** | ||
| * Process and transform errors of `deepMergeWithoutCollision` | ||
| */ | ||
| export interface ErrorProcessor { | ||
| /** | ||
| * @param param Error information | ||
| * @returns An error object | ||
| */ | ||
| (param: ErrorProcessorParam): unknown; | ||
| } | ||
| /** | ||
| * Param to pass to {@link ErrorProcessor} should {@link deepMergeWithoutCollision} fails | ||
| */ | ||
| export declare type ErrorProcessorParam = PropertyCollision; | ||
| /** | ||
| * Code of errors that `deepMergeWithoutCollision may cause | ||
| */ | ||
| export declare const enum ErrorType { | ||
| /** | ||
| * Indicates that two merging objects possess properties of same name | ||
| */ | ||
| PropertyCollision = 1 | ||
| } | ||
| /** | ||
| * Param to pass to {@link ErrorProcessor} should two merging objects possess properties of same name | ||
| */ | ||
| export interface PropertyCollision { | ||
| /** | ||
| * Type of error | ||
| * @discriminator | ||
| */ | ||
| type: ErrorType.PropertyCollision; | ||
| /** | ||
| * Two merging object | ||
| */ | ||
| objects: [object, object]; | ||
| /** | ||
| * Name of conflicting properties | ||
| */ | ||
| key: string; | ||
| /** | ||
| * Values of conflicting properties | ||
| */ | ||
| values: [unknown, unknown]; | ||
| } |
+65
-35
@@ -6,24 +6,23 @@ "use strict"; | ||
| * Merge two objects of the same interface | ||
| * | ||
| * `b` is prioritized for overlapping non-object properties | ||
| * | ||
| * @param a Object or value to merge | ||
| * @param b Object or value to merge | ||
| * @param left Object or value to merge | ||
| * @param right Object or value to merge | ||
| * @param resolveConflict Function that resolves property conflict | ||
| * @returns Result of the merge | ||
| */ | ||
| function deepMergeOverwrite(a, b) { | ||
| if (!isObject(a) || !isObject(b)) | ||
| return b; | ||
| function deepMergeWithPreference(left, right, resolveConflict) { | ||
| if (!isObject(left) || !isObject(right)) { | ||
| return resolveConflict([left, right]) ? right : left; | ||
| } | ||
| const result = {}; | ||
| for (const [key, aValue] of Object.entries(a)) { | ||
| if (key in b) { | ||
| const bValue = b[key]; | ||
| result[key] = deepMergeOverwrite(aValue, bValue); | ||
| for (const [key, leftValue] of Object.entries(left)) { | ||
| if (key in right) { | ||
| const rightValue = right[key]; | ||
| result[key] = deepMergeWithPreference(leftValue, rightValue, resolveConflict); | ||
| } | ||
| else { | ||
| result[key] = aValue; | ||
| result[key] = leftValue; | ||
| } | ||
| } | ||
| for (const [key, bValue] of Object.entries(b)) { | ||
| if (key in a) | ||
| for (const [key, bValue] of Object.entries(right)) { | ||
| if (key in left) | ||
| continue; | ||
@@ -34,2 +33,30 @@ result[key] = bValue; | ||
| } | ||
| exports.deepMergeWithPreference = deepMergeWithPreference; | ||
| /** | ||
| * Choice to be made | ||
| */ | ||
| var PropertyPreference; | ||
| (function (PropertyPreference) { | ||
| /** | ||
| * Choose the left value (`values[0]`) | ||
| */ | ||
| PropertyPreference[PropertyPreference["Left"] = 0] = "Left"; | ||
| /** | ||
| * Choose the right value (`values[1]`) | ||
| */ | ||
| PropertyPreference[PropertyPreference["Right"] = 1] = "Right"; | ||
| })(PropertyPreference = exports.PropertyPreference || (exports.PropertyPreference = {})); | ||
| const PREFER_RIGHT = () => 1 /* Right */; | ||
| /** | ||
| * Merge two objects of the same interface | ||
| * | ||
| * `left` is prioritized for overlapping non-object properties | ||
| * | ||
| * @param left Object or value to merge | ||
| * @param right Object or value to merge | ||
| * @returns Result of the merge | ||
| */ | ||
| function deepMergeOverwrite(left, right) { | ||
| return deepMergeWithPreference(left, right, PREFER_RIGHT); | ||
| } | ||
| exports.deepMergeOverwrite = deepMergeOverwrite; | ||
@@ -44,14 +71,14 @@ const DMWOC_DEF_ERR_HDLR = param => { | ||
| * | ||
| * @param a Object to merge | ||
| * @param b Object to merge | ||
| * @param left Object to merge | ||
| * @param right Object to merge | ||
| * @param onerror Function to handle should error occurs | ||
| * @returns A merged object of `a` and `b` | ||
| */ | ||
| function deepMergeWithoutCollision(a, b, onerror = DMWOC_DEF_ERR_HDLR) { | ||
| function deepMergeWithoutCollision(left, right, onerror = DMWOC_DEF_ERR_HDLR) { | ||
| const result = {}; | ||
| for (const [key, aValue] of Object.entries(a)) { | ||
| if (key in b) { | ||
| const bValue = b[key]; | ||
| if (isObject(aValue) && isObject(bValue)) { | ||
| result[key] = deepMergeWithoutCollision(aValue, bValue, onerror); | ||
| for (const [key, leftValue] of Object.entries(left)) { | ||
| if (key in right) { | ||
| const rightValue = right[key]; | ||
| if (isObject(leftValue) && isObject(rightValue)) { | ||
| result[key] = deepMergeWithoutCollision(leftValue, rightValue, onerror); | ||
| } | ||
@@ -61,5 +88,5 @@ else { | ||
| type: 1 /* PropertyCollision */, | ||
| objects: [a, b], | ||
| objects: [left, right], | ||
| key, | ||
| values: [aValue, bValue] | ||
| values: [leftValue, rightValue] | ||
| }); | ||
@@ -69,7 +96,7 @@ } | ||
| else { | ||
| result[key] = aValue; | ||
| result[key] = leftValue; | ||
| } | ||
| } | ||
| for (const [key, bValue] of Object.entries(b)) { | ||
| if (key in a) | ||
| for (const [key, bValue] of Object.entries(right)) { | ||
| if (key in left) | ||
| continue; | ||
@@ -81,9 +108,12 @@ result[key] = bValue; | ||
| exports.deepMergeWithoutCollision = deepMergeWithoutCollision; | ||
| /* istanbul ignore next */ | ||
| (function (deepMergeWithoutCollision) { | ||
| let ErrorType; | ||
| (function (ErrorType) { | ||
| ErrorType[ErrorType["PropertyCollision"] = 1] = "PropertyCollision"; | ||
| })(ErrorType = deepMergeWithoutCollision.ErrorType || (deepMergeWithoutCollision.ErrorType = {})); | ||
| })(deepMergeWithoutCollision = exports.deepMergeWithoutCollision || (exports.deepMergeWithoutCollision = {})); | ||
| /** | ||
| * Code of errors that `deepMergeWithoutCollision may cause | ||
| */ | ||
| var ErrorType; | ||
| (function (ErrorType) { | ||
| /** | ||
| * Indicates that two merging objects possess properties of same name | ||
| */ | ||
| ErrorType[ErrorType["PropertyCollision"] = 1] = "PropertyCollision"; | ||
| })(ErrorType = exports.ErrorType || (exports.ErrorType = {})); | ||
| //# sourceMappingURL=deep-merge.js.map |
+73
-34
| const isObject = value => value && typeof value === 'object' && !Array.isArray(value); | ||
| /** | ||
| * Merge two objects of the same interface | ||
| * | ||
| * `b` is prioritized for overlapping non-object properties | ||
| * | ||
| * @param a Object or value to merge | ||
| * @param b Object or value to merge | ||
| * @param left Object or value to merge | ||
| * @param right Object or value to merge | ||
| * @param resolveConflict Function that resolves property conflict | ||
| * @returns Result of the merge | ||
@@ -13,17 +11,20 @@ */ | ||
| export function deepMergeOverwrite(a, b) { | ||
| if (!isObject(a) || !isObject(b)) return b; | ||
| export function deepMergeWithPreference(left, right, resolveConflict) { | ||
| if (!isObject(left) || !isObject(right)) { | ||
| return resolveConflict([left, right]) ? right : left; | ||
| } | ||
| const result = {}; | ||
| for (const [key, aValue] of Object.entries(a)) { | ||
| if (key in b) { | ||
| const bValue = b[key]; | ||
| result[key] = deepMergeOverwrite(aValue, bValue); | ||
| for (const [key, leftValue] of Object.entries(left)) { | ||
| if (key in right) { | ||
| const rightValue = right[key]; | ||
| result[key] = deepMergeWithPreference(leftValue, rightValue, resolveConflict); | ||
| } else { | ||
| result[key] = aValue; | ||
| result[key] = leftValue; | ||
| } | ||
| } | ||
| for (const [key, bValue] of Object.entries(b)) { | ||
| if (key in a) continue; | ||
| for (const [key, bValue] of Object.entries(right)) { | ||
| if (key in left) continue; | ||
| result[key] = bValue; | ||
@@ -34,3 +35,38 @@ } | ||
| } | ||
| /** | ||
| * Choice to be made | ||
| */ | ||
| export var PropertyPreference; | ||
| (function (PropertyPreference) { | ||
| /** | ||
| * Choose the left value (`values[0]`) | ||
| */ | ||
| PropertyPreference[PropertyPreference["Left"] = 0] = "Left"; | ||
| /** | ||
| * Choose the right value (`values[1]`) | ||
| */ | ||
| PropertyPreference[PropertyPreference["Right"] = 1] = "Right"; | ||
| })(PropertyPreference || (PropertyPreference = {})); | ||
| const PREFER_RIGHT = () => 1 | ||
| /* Right */ | ||
| ; | ||
| /** | ||
| * Merge two objects of the same interface | ||
| * | ||
| * `left` is prioritized for overlapping non-object properties | ||
| * | ||
| * @param left Object or value to merge | ||
| * @param right Object or value to merge | ||
| * @returns Result of the merge | ||
| */ | ||
| export function deepMergeOverwrite(left, right) { | ||
| return deepMergeWithPreference(left, right, PREFER_RIGHT); | ||
| } | ||
| const DMWOC_DEF_ERR_HDLR = param => { | ||
@@ -44,4 +80,4 @@ throw Object.assign(new TypeError(`Property collision`), param); | ||
| * | ||
| * @param a Object to merge | ||
| * @param b Object to merge | ||
| * @param left Object to merge | ||
| * @param right Object to merge | ||
| * @param onerror Function to handle should error occurs | ||
@@ -52,11 +88,11 @@ * @returns A merged object of `a` and `b` | ||
| export function deepMergeWithoutCollision(a, b, onerror = DMWOC_DEF_ERR_HDLR) { | ||
| export function deepMergeWithoutCollision(left, right, onerror = DMWOC_DEF_ERR_HDLR) { | ||
| const result = {}; | ||
| for (const [key, aValue] of Object.entries(a)) { | ||
| if (key in b) { | ||
| const bValue = b[key]; | ||
| for (const [key, leftValue] of Object.entries(left)) { | ||
| if (key in right) { | ||
| const rightValue = right[key]; | ||
| if (isObject(aValue) && isObject(bValue)) { | ||
| result[key] = deepMergeWithoutCollision(aValue, bValue, onerror); | ||
| if (isObject(leftValue) && isObject(rightValue)) { | ||
| result[key] = deepMergeWithoutCollision(leftValue, rightValue, onerror); | ||
| } else { | ||
@@ -67,14 +103,14 @@ throw onerror({ | ||
| , | ||
| objects: [a, b], | ||
| objects: [left, right], | ||
| key, | ||
| values: [aValue, bValue] | ||
| values: [leftValue, rightValue] | ||
| }); | ||
| } | ||
| } else { | ||
| result[key] = aValue; | ||
| result[key] = leftValue; | ||
| } | ||
| } | ||
| for (const [key, bValue] of Object.entries(b)) { | ||
| if (key in a) continue; | ||
| for (const [key, bValue] of Object.entries(right)) { | ||
| if (key in left) continue; | ||
| result[key] = bValue; | ||
@@ -85,10 +121,13 @@ } | ||
| } | ||
| /* istanbul ignore next */ | ||
| /** | ||
| * Code of errors that `deepMergeWithoutCollision may cause | ||
| */ | ||
| (function (deepMergeWithoutCollision) { | ||
| let ErrorType; | ||
| export var ErrorType; | ||
| (function (ErrorType) { | ||
| ErrorType[ErrorType["PropertyCollision"] = 1] = "PropertyCollision"; | ||
| })(ErrorType = deepMergeWithoutCollision.ErrorType || (deepMergeWithoutCollision.ErrorType = {})); | ||
| })(deepMergeWithoutCollision || (deepMergeWithoutCollision = {})); //# sourceMappingURL=deep-merge.js.map | ||
| (function (ErrorType) { | ||
| /** | ||
| * Indicates that two merging objects possess properties of same name | ||
| */ | ||
| ErrorType[ErrorType["PropertyCollision"] = 1] = "PropertyCollision"; | ||
| })(ErrorType || (ErrorType = {})); //# sourceMappingURL=deep-merge.js.map |
+82
-21
| import { SimpleDeepMerge } from './utils/types'; | ||
| /** | ||
| * Merge two objects of the same interface | ||
| * @param left Object or value to merge | ||
| * @param right Object or value to merge | ||
| * @param resolveConflict Function that resolves property conflict | ||
| * @returns Result of the merge | ||
| */ | ||
| export declare function deepMergeWithPreference<Value>(left: Value, right: Value, resolveConflict: PropertyConflictResolver): Value; | ||
| /** | ||
| * Decides which property should make it to the merged object | ||
| */ | ||
| export interface PropertyConflictResolver { | ||
| /** | ||
| * @param values Pair of conflicting properties | ||
| * @returns Property choice | ||
| */ | ||
| (values: [unknown, unknown]): PropertyPreference; | ||
| } | ||
| /** | ||
| * Choice to be made | ||
| */ | ||
| export declare const enum PropertyPreference { | ||
| /** | ||
| * Choose the left value (`values[0]`) | ||
| */ | ||
| Left = 0, | ||
| /** | ||
| * Choose the right value (`values[1]`) | ||
| */ | ||
| Right = 1 | ||
| } | ||
| /** | ||
| * Merge two objects of the same interface | ||
| * | ||
| * `b` is prioritized for overlapping non-object properties | ||
| * `left` is prioritized for overlapping non-object properties | ||
| * | ||
| * @param a Object or value to merge | ||
| * @param b Object or value to merge | ||
| * @param left Object or value to merge | ||
| * @param right Object or value to merge | ||
| * @returns Result of the merge | ||
| */ | ||
| export declare function deepMergeOverwrite<Value>(a: Value, b: Value): Value; | ||
| export declare function deepMergeOverwrite<Value>(left: Value, right: Value): Value; | ||
| /** | ||
@@ -17,22 +48,52 @@ * Merge two objects | ||
| * | ||
| * @param a Object to merge | ||
| * @param b Object to merge | ||
| * @param left Object to merge | ||
| * @param right Object to merge | ||
| * @param onerror Function to handle should error occurs | ||
| * @returns A merged object of `a` and `b` | ||
| */ | ||
| export declare function deepMergeWithoutCollision<A extends object, B extends object>(a: A, b: B, onerror?: deepMergeWithoutCollision.ErrorProcessor): SimpleDeepMerge<A, B>; | ||
| export declare namespace deepMergeWithoutCollision { | ||
| interface ErrorProcessor { | ||
| (param: ErrorProcessorParam): unknown; | ||
| } | ||
| type ErrorProcessorParam = PropertyCollision; | ||
| const enum ErrorType { | ||
| PropertyCollision = 1 | ||
| } | ||
| interface PropertyCollision { | ||
| type: ErrorType.PropertyCollision; | ||
| objects: [object, object]; | ||
| key: string | symbol; | ||
| values: [unknown, unknown]; | ||
| } | ||
| export declare function deepMergeWithoutCollision<Left extends object, Right extends object>(left: Left, right: Right, onerror?: ErrorProcessor): SimpleDeepMerge<Left, Right>; | ||
| /** | ||
| * Process and transform errors of `deepMergeWithoutCollision` | ||
| */ | ||
| export interface ErrorProcessor { | ||
| /** | ||
| * @param param Error information | ||
| * @returns An error object | ||
| */ | ||
| (param: ErrorProcessorParam): unknown; | ||
| } | ||
| /** | ||
| * Param to pass to {@link ErrorProcessor} should {@link deepMergeWithoutCollision} fails | ||
| */ | ||
| export declare type ErrorProcessorParam = PropertyCollision; | ||
| /** | ||
| * Code of errors that `deepMergeWithoutCollision may cause | ||
| */ | ||
| export declare const enum ErrorType { | ||
| /** | ||
| * Indicates that two merging objects possess properties of same name | ||
| */ | ||
| PropertyCollision = 1 | ||
| } | ||
| /** | ||
| * Param to pass to {@link ErrorProcessor} should two merging objects possess properties of same name | ||
| */ | ||
| export interface PropertyCollision { | ||
| /** | ||
| * Type of error | ||
| * @discriminator | ||
| */ | ||
| type: ErrorType.PropertyCollision; | ||
| /** | ||
| * Two merging object | ||
| */ | ||
| objects: [object, object]; | ||
| /** | ||
| * Name of conflicting properties | ||
| */ | ||
| key: string; | ||
| /** | ||
| * Values of conflicting properties | ||
| */ | ||
| values: [unknown, unknown]; | ||
| } |
+1
-1
| { | ||
| "name": "@tsfun/object", | ||
| "version": "0.0.12", | ||
| "version": "0.0.13", | ||
| "description": "Utilities related to objects", | ||
@@ -5,0 +5,0 @@ "author": "Hoàng Văn Khải <hvksmr1996@gmail.com>", |
47900
11.83%1211
17.92%