diff --git a/CHANGELOG.md b/CHANGELOG.md index 99b432ba..83c6627e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,25 @@ # Changelog All notable changes to this project will be documented in this file. Dates are displayed in UTC. +# [4.0.0](https://github.com/RebeccaStevens/deepmerge-ts/compare/v3.0.1...v4.0.0) (2022-02-26) + + +### Bug Fixes + +* improve meta data typings ([#61](https://github.com/RebeccaStevens/deepmerge-ts/issues/61)) ([9a881d3](https://github.com/RebeccaStevens/deepmerge-ts/commit/9a881d3e55762da03b0d0f465d7e958d81fd0958)) + + +### Features + +* allow for default merging via a special return value ([658d1fd](https://github.com/RebeccaStevens/deepmerge-ts/commit/658d1fd454fe095e6c7f2be22ccf4823fe0ea6ef)) +* allow for implicit default merging ([1d5e617](https://github.com/RebeccaStevens/deepmerge-ts/commit/1d5e617bc4980f64a75fa9da1397979b2310fc06)) +* allow for skipping properties completely via a special return value ([#64](https://github.com/RebeccaStevens/deepmerge-ts/issues/64)) ([676f2f6](https://github.com/RebeccaStevens/deepmerge-ts/commit/676f2f6593d6baf0e1b31f29c83bac7c392e7ce2)) + + +### BREAKING CHANGES + +* MetaMetaData now must extends DeepMergeBuiltInMetaData + ## [3.0.1](https://github.com/RebeccaStevens/deepmerge-ts/compare/v3.0.0...v3.0.1) (2022-02-22) diff --git a/dist/deno/deepmerge.ts b/dist/deno/deepmerge.ts index 364504ec..e6e5da42 100644 --- a/dist/deno/deepmerge.ts +++ b/dist/deno/deepmerge.ts @@ -20,13 +20,21 @@ import { } from "./utils.ts"; const defaultMergeFunctions = { - mergeMaps, - mergeSets, - mergeArrays, - mergeRecords, + mergeMaps: defaultMergeMaps, + mergeSets: defaultMergeSets, + mergeArrays: defaultMergeArrays, + mergeRecords: defaultMergeRecords, mergeOthers: leaf, } as const; +/** + * Special values that tell deepmerge-ts to perform a certain action. + */ +const actions = { + defaultMerge: Symbol("deepmerge-ts: default merge"), + skip: Symbol("deepmerge-ts: skip"), +} as const; + /** * The default function to update meta data. */ @@ -87,9 +95,7 @@ export function deepmergeCustom< export function deepmergeCustom< PMF extends Partial, MetaData, - MetaMetaData extends Readonly< - Record - > = DeepMergeBuiltInMetaData + MetaMetaData extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData >( options: DeepMergeOptions, rootMetaData?: MetaData @@ -100,7 +106,7 @@ export function deepmergeCustom< export function deepmergeCustom< PMF extends Partial, MetaData, - MetaMetaData extends Readonly> + MetaMetaData extends DeepMergeBuiltInMetaData >( options: DeepMergeOptions, rootMetaData?: MetaData @@ -140,7 +146,7 @@ export function deepmergeCustom< * * @param options - The options the user specified */ -function getUtils>>( +function getUtils( options: DeepMergeOptions, customizedDeepmerge: DeepMergeMergeFunctionUtils["deepmerge"] ): DeepMergeMergeFunctionUtils { @@ -164,6 +170,8 @@ function getUtils>>( MM >["metaDataUpdater"], deepmerge: customizedDeepmerge, + useImplicitDefaultMerging: options.enableImplicitDefaultMerging ?? false, + actions, }; } @@ -177,17 +185,17 @@ function mergeUnknowns< U extends DeepMergeMergeFunctionUtils, MF extends DeepMergeMergeFunctionsURIs, M, - MM extends Readonly> + MM extends DeepMergeBuiltInMetaData >(values: Ts, utils: U, meta: M | undefined): DeepMergeHKT { if (values.length === 0) { return undefined as DeepMergeHKT; } if (values.length === 1) { - return utils.mergeFunctions.mergeOthers( - values, - utils, - meta - ) as DeepMergeHKT; + return mergeOthers(values, utils, meta) as DeepMergeHKT< + Ts, + MF, + M + >; } const type = getObjectType(values[0]); @@ -200,49 +208,49 @@ function mergeUnknowns< continue; } - return utils.mergeFunctions.mergeOthers( - values, - utils, - meta - ) as DeepMergeHKT; + return mergeOthers(values, utils, meta) as DeepMergeHKT< + Ts, + MF, + M + >; } } switch (type) { case ObjectType.RECORD: - return utils.mergeFunctions.mergeRecords( + return mergeRecords( values as ReadonlyArray>>, utils, meta ) as DeepMergeHKT; case ObjectType.ARRAY: - return utils.mergeFunctions.mergeArrays( + return mergeArrays( values as ReadonlyArray>>, utils, meta ) as DeepMergeHKT; case ObjectType.SET: - return utils.mergeFunctions.mergeSets( + return mergeSets( values as ReadonlyArray>>, utils, meta ) as DeepMergeHKT; case ObjectType.MAP: - return utils.mergeFunctions.mergeMaps( + return mergeMaps( values as ReadonlyArray>>, utils, meta ) as DeepMergeHKT; default: - return utils.mergeFunctions.mergeOthers( - values, - utils, - meta - ) as DeepMergeHKT; + return mergeOthers(values, utils, meta) as DeepMergeHKT< + Ts, + MF, + M + >; } } @@ -252,6 +260,148 @@ function mergeUnknowns< * @param values - The records. */ function mergeRecords< + U extends DeepMergeMergeFunctionUtils, + MF extends DeepMergeMergeFunctionsURIs, + M, + MM extends DeepMergeBuiltInMetaData +>( + values: ReadonlyArray>>, + utils: U, + meta: M | undefined +) { + const result = utils.mergeFunctions.mergeRecords(values, utils, meta); + + if ( + result === actions.defaultMerge || + (utils.useImplicitDefaultMerging && + result === undefined && + utils.mergeFunctions.mergeRecords !== + utils.defaultMergeFunctions.mergeRecords) + ) { + return utils.defaultMergeFunctions.mergeRecords< + ReadonlyArray>>, + U, + MF, + M, + MM + >(values, utils, meta); + } + + return result; +} + +/** + * Merge arrays. + * + * @param values - The arrays. + */ +function mergeArrays< + U extends DeepMergeMergeFunctionUtils, + M, + MM extends DeepMergeBuiltInMetaData +>( + values: ReadonlyArray>>, + utils: U, + meta: M | undefined +) { + const result = utils.mergeFunctions.mergeArrays(values, utils, meta); + + if ( + result === actions.defaultMerge || + (utils.useImplicitDefaultMerging && + result === undefined && + utils.mergeFunctions.mergeArrays !== + utils.defaultMergeFunctions.mergeArrays) + ) { + return utils.defaultMergeFunctions.mergeArrays(values); + } + return result; +} + +/** + * Merge sets. + * + * @param values - The sets. + */ +function mergeSets< + U extends DeepMergeMergeFunctionUtils, + M, + MM extends DeepMergeBuiltInMetaData +>( + values: ReadonlyArray>>, + utils: U, + meta: M | undefined +) { + const result = utils.mergeFunctions.mergeSets(values, utils, meta); + + if ( + result === actions.defaultMerge || + (utils.useImplicitDefaultMerging && + result === undefined && + utils.mergeFunctions.mergeSets !== utils.defaultMergeFunctions.mergeSets) + ) { + return utils.defaultMergeFunctions.mergeSets(values); + } + return result; +} + +/** + * Merge maps. + * + * @param values - The maps. + */ +function mergeMaps< + U extends DeepMergeMergeFunctionUtils, + M, + MM extends DeepMergeBuiltInMetaData +>( + values: ReadonlyArray>>, + utils: U, + meta: M | undefined +) { + const result = utils.mergeFunctions.mergeMaps(values, utils, meta); + + if ( + result === actions.defaultMerge || + (utils.useImplicitDefaultMerging && + result === undefined && + utils.mergeFunctions.mergeMaps !== utils.defaultMergeFunctions.mergeMaps) + ) { + return utils.defaultMergeFunctions.mergeMaps(values); + } + return result; +} + +/** + * Merge other things. + * + * @param values - The other things. + */ +function mergeOthers< + U extends DeepMergeMergeFunctionUtils, + M, + MM extends DeepMergeBuiltInMetaData +>(values: ReadonlyArray, utils: U, meta: M | undefined) { + const result = utils.mergeFunctions.mergeOthers(values, utils, meta); + + if ( + result === actions.defaultMerge || + (utils.useImplicitDefaultMerging && + result === undefined && + utils.mergeFunctions.mergeOthers !== + utils.defaultMergeFunctions.mergeOthers) + ) { + return utils.defaultMergeFunctions.mergeOthers(values); + } + return result; +} + +/** + * The default strategy to merge records. + * + * @param values - The records. + */ +function defaultMergeRecords< Ts extends ReadonlyArray>, U extends DeepMergeMergeFunctionUtils, MF extends DeepMergeMergeFunctionsURIs, @@ -278,11 +428,17 @@ function mergeRecords< parents: values, } as unknown as MM); - result[key] = mergeUnknowns, U, MF, M, MM>( + const propertyResult = mergeUnknowns, U, MF, M, MM>( propValues, utils, updatedMeta ); + + if (propertyResult === actions.skip) { + continue; + } + + result[key] = propertyResult; } /* eslint-enable functional/no-loop-statement, functional/no-conditional-statement */ @@ -291,11 +447,11 @@ function mergeRecords< } /** - * Merge arrays. + * The default strategy to merge arrays. * * @param values - The arrays. */ -function mergeArrays< +function defaultMergeArrays< Ts extends ReadonlyArray>, MF extends DeepMergeMergeFunctionsURIs, M @@ -304,31 +460,29 @@ function mergeArrays< } /** - * Merge sets. + * The default strategy to merge sets. * * @param values - The sets. */ -function mergeSets>>>( - values: Ts -) { +function defaultMergeSets< + Ts extends ReadonlyArray>> +>(values: Ts) { return new Set(getIterableOfIterables(values)) as DeepMergeSetsDefaultHKT; } /** - * Merge maps. + * The default strategy to merge maps. * * @param values - The maps. */ -function mergeMaps< +function defaultMergeMaps< Ts extends ReadonlyArray>> >(values: Ts) { return new Map(getIterableOfIterables(values)) as DeepMergeMapsDefaultHKT; } /** - * Merge "other" things. - * - * @param values - The values. + * Get the last value in the given array. */ function leaf>(values: Ts) { return values[values.length - 1]; diff --git a/dist/deno/types/options.ts b/dist/deno/types/options.ts index ded089f3..59602697 100644 --- a/dist/deno/types/options.ts +++ b/dist/deno/types/options.ts @@ -7,27 +7,25 @@ import type { DeepMergeBuiltInMetaData } from "./merging.ts"; */ export type DeepMergeOptions< M, - MM extends Record = DeepMergeBuiltInMetaData -> = Partial>>; + MM extends Readonly> = DeepMergeBuiltInMetaData +> = Partial>; -type MetaDataUpdater> = ( +type MetaDataUpdater = ( previousMeta: M | undefined, - metaMeta: MM + metaMeta: Readonly> ) => M; /** * All the options the user can pass to customize deepmerge. */ -type DeepMergeOptionsFull< - M, - MM extends Record -> = Readonly<{ +type DeepMergeOptionsFull = Readonly<{ mergeRecords: DeepMergeMergeFunctions["mergeRecords"] | false; mergeArrays: DeepMergeMergeFunctions["mergeArrays"] | false; mergeMaps: DeepMergeMergeFunctions["mergeMaps"] | false; mergeSets: DeepMergeMergeFunctions["mergeSets"] | false; mergeOthers: DeepMergeMergeFunctions["mergeOthers"]; metaDataUpdater: MetaDataUpdater; + enableImplicitDefaultMerging: boolean; }>; /** @@ -35,7 +33,7 @@ type DeepMergeOptionsFull< */ type DeepMergeMergeFunctions< M, - MM extends Record + MM extends DeepMergeBuiltInMetaData > = Readonly<{ mergeRecords: < Ts extends ReadonlyArray>>, @@ -88,10 +86,15 @@ type DeepMergeMergeFunctions< */ export type DeepMergeMergeFunctionUtils< M, - MM extends Record + MM extends DeepMergeBuiltInMetaData > = Readonly<{ mergeFunctions: DeepMergeMergeFunctions; defaultMergeFunctions: DeepMergeMergeFunctionsDefaults; metaDataUpdater: MetaDataUpdater; deepmerge: >(...values: Ts) => unknown; + useImplicitDefaultMerging: boolean; + actions: Readonly<{ + defaultMerge: symbol; + skip: symbol; + }>; }>; diff --git a/dist/node/index.cjs b/dist/node/index.cjs index 4990ef8c..66b1a8f9 100644 --- a/dist/node/index.cjs +++ b/dist/node/index.cjs @@ -79,12 +79,19 @@ function getIterableOfIterables(iterables) { } const defaultMergeFunctions = { - mergeMaps, - mergeSets, - mergeArrays, - mergeRecords, + mergeMaps: defaultMergeMaps, + mergeSets: defaultMergeSets, + mergeArrays: defaultMergeArrays, + mergeRecords: defaultMergeRecords, mergeOthers: leaf, }; +/** + * Special values that tell deepmerge-ts to perform a certain action. + */ +const actions = { + defaultMerge: Symbol("deepmerge-ts: default merge"), + skip: Symbol("deepmerge-ts: skip"), +}; /** * The default function to update meta data. */ @@ -115,7 +122,7 @@ function deepmergeCustom(options, rootMetaData) { * @param options - The options the user specified */ function getUtils(options, customizedDeepmerge) { - var _a; + var _a, _b; return { defaultMergeFunctions, mergeFunctions: { @@ -126,6 +133,8 @@ function getUtils(options, customizedDeepmerge) { }, metaDataUpdater: ((_a = options.metaDataUpdater) !== null && _a !== void 0 ? _a : defaultMetaDataUpdater), deepmerge: customizedDeepmerge, + useImplicitDefaultMerging: (_b = options.enableImplicitDefaultMerging) !== null && _b !== void 0 ? _b : false, + actions, }; } /** @@ -138,7 +147,7 @@ function mergeUnknowns(values, utils, meta) { return undefined; } if (values.length === 1) { - return utils.mergeFunctions.mergeOthers(values, utils, meta); + return mergeOthers(values, utils, meta); } const type = getObjectType(values[0]); // eslint-disable-next-line functional/no-conditional-statement -- add an early escape for better performance. @@ -148,20 +157,20 @@ function mergeUnknowns(values, utils, meta) { if (getObjectType(values[mutableIndex]) === type) { continue; } - return utils.mergeFunctions.mergeOthers(values, utils, meta); + return mergeOthers(values, utils, meta); } } switch (type) { case 1 /* RECORD */: - return utils.mergeFunctions.mergeRecords(values, utils, meta); + return mergeRecords(values, utils, meta); case 2 /* ARRAY */: - return utils.mergeFunctions.mergeArrays(values, utils, meta); + return mergeArrays(values, utils, meta); case 3 /* SET */: - return utils.mergeFunctions.mergeSets(values, utils, meta); + return mergeSets(values, utils, meta); case 4 /* MAP */: - return utils.mergeFunctions.mergeMaps(values, utils, meta); + return mergeMaps(values, utils, meta); default: - return utils.mergeFunctions.mergeOthers(values, utils, meta); + return mergeOthers(values, utils, meta); } } /** @@ -170,6 +179,84 @@ function mergeUnknowns(values, utils, meta) { * @param values - The records. */ function mergeRecords(values, utils, meta) { + const result = utils.mergeFunctions.mergeRecords(values, utils, meta); + if (result === actions.defaultMerge || + (utils.useImplicitDefaultMerging && + result === undefined && + utils.mergeFunctions.mergeRecords !== + utils.defaultMergeFunctions.mergeRecords)) { + return utils.defaultMergeFunctions.mergeRecords(values, utils, meta); + } + return result; +} +/** + * Merge arrays. + * + * @param values - The arrays. + */ +function mergeArrays(values, utils, meta) { + const result = utils.mergeFunctions.mergeArrays(values, utils, meta); + if (result === actions.defaultMerge || + (utils.useImplicitDefaultMerging && + result === undefined && + utils.mergeFunctions.mergeArrays !== + utils.defaultMergeFunctions.mergeArrays)) { + return utils.defaultMergeFunctions.mergeArrays(values); + } + return result; +} +/** + * Merge sets. + * + * @param values - The sets. + */ +function mergeSets(values, utils, meta) { + const result = utils.mergeFunctions.mergeSets(values, utils, meta); + if (result === actions.defaultMerge || + (utils.useImplicitDefaultMerging && + result === undefined && + utils.mergeFunctions.mergeSets !== utils.defaultMergeFunctions.mergeSets)) { + return utils.defaultMergeFunctions.mergeSets(values); + } + return result; +} +/** + * Merge maps. + * + * @param values - The maps. + */ +function mergeMaps(values, utils, meta) { + const result = utils.mergeFunctions.mergeMaps(values, utils, meta); + if (result === actions.defaultMerge || + (utils.useImplicitDefaultMerging && + result === undefined && + utils.mergeFunctions.mergeMaps !== utils.defaultMergeFunctions.mergeMaps)) { + return utils.defaultMergeFunctions.mergeMaps(values); + } + return result; +} +/** + * Merge other things. + * + * @param values - The other things. + */ +function mergeOthers(values, utils, meta) { + const result = utils.mergeFunctions.mergeOthers(values, utils, meta); + if (result === actions.defaultMerge || + (utils.useImplicitDefaultMerging && + result === undefined && + utils.mergeFunctions.mergeOthers !== + utils.defaultMergeFunctions.mergeOthers)) { + return utils.defaultMergeFunctions.mergeOthers(values); + } + return result; +} +/** + * The default strategy to merge records. + * + * @param values - The records. + */ +function defaultMergeRecords(values, utils, meta) { const result = {}; /* eslint-disable functional/no-loop-statement, functional/no-conditional-statement -- using a loop here is more performant. */ for (const key of getKeys(values)) { @@ -184,39 +271,41 @@ function mergeRecords(values, utils, meta) { key, parents: values, }); - result[key] = mergeUnknowns(propValues, utils, updatedMeta); + const propertyResult = mergeUnknowns(propValues, utils, updatedMeta); + if (propertyResult === actions.skip) { + continue; + } + result[key] = propertyResult; } /* eslint-enable functional/no-loop-statement, functional/no-conditional-statement */ return result; } /** - * Merge arrays. + * The default strategy to merge arrays. * * @param values - The arrays. */ -function mergeArrays(values) { +function defaultMergeArrays(values) { return values.flat(); } /** - * Merge sets. + * The default strategy to merge sets. * * @param values - The sets. */ -function mergeSets(values) { +function defaultMergeSets(values) { return new Set(getIterableOfIterables(values)); } /** - * Merge maps. + * The default strategy to merge maps. * * @param values - The maps. */ -function mergeMaps(values) { +function defaultMergeMaps(values) { return new Map(getIterableOfIterables(values)); } /** - * Merge "other" things. - * - * @param values - The values. + * Get the last value in the given array. */ function leaf(values) { return values[values.length - 1]; diff --git a/dist/node/index.mjs b/dist/node/index.mjs index 57a8ccc0..5a10d1d0 100644 --- a/dist/node/index.mjs +++ b/dist/node/index.mjs @@ -75,12 +75,19 @@ function getIterableOfIterables(iterables) { } const defaultMergeFunctions = { - mergeMaps, - mergeSets, - mergeArrays, - mergeRecords, + mergeMaps: defaultMergeMaps, + mergeSets: defaultMergeSets, + mergeArrays: defaultMergeArrays, + mergeRecords: defaultMergeRecords, mergeOthers: leaf, }; +/** + * Special values that tell deepmerge-ts to perform a certain action. + */ +const actions = { + defaultMerge: Symbol("deepmerge-ts: default merge"), + skip: Symbol("deepmerge-ts: skip"), +}; /** * The default function to update meta data. */ @@ -111,7 +118,7 @@ function deepmergeCustom(options, rootMetaData) { * @param options - The options the user specified */ function getUtils(options, customizedDeepmerge) { - var _a; + var _a, _b; return { defaultMergeFunctions, mergeFunctions: { @@ -122,6 +129,8 @@ function getUtils(options, customizedDeepmerge) { }, metaDataUpdater: ((_a = options.metaDataUpdater) !== null && _a !== void 0 ? _a : defaultMetaDataUpdater), deepmerge: customizedDeepmerge, + useImplicitDefaultMerging: (_b = options.enableImplicitDefaultMerging) !== null && _b !== void 0 ? _b : false, + actions, }; } /** @@ -134,7 +143,7 @@ function mergeUnknowns(values, utils, meta) { return undefined; } if (values.length === 1) { - return utils.mergeFunctions.mergeOthers(values, utils, meta); + return mergeOthers(values, utils, meta); } const type = getObjectType(values[0]); // eslint-disable-next-line functional/no-conditional-statement -- add an early escape for better performance. @@ -144,20 +153,20 @@ function mergeUnknowns(values, utils, meta) { if (getObjectType(values[mutableIndex]) === type) { continue; } - return utils.mergeFunctions.mergeOthers(values, utils, meta); + return mergeOthers(values, utils, meta); } } switch (type) { case 1 /* RECORD */: - return utils.mergeFunctions.mergeRecords(values, utils, meta); + return mergeRecords(values, utils, meta); case 2 /* ARRAY */: - return utils.mergeFunctions.mergeArrays(values, utils, meta); + return mergeArrays(values, utils, meta); case 3 /* SET */: - return utils.mergeFunctions.mergeSets(values, utils, meta); + return mergeSets(values, utils, meta); case 4 /* MAP */: - return utils.mergeFunctions.mergeMaps(values, utils, meta); + return mergeMaps(values, utils, meta); default: - return utils.mergeFunctions.mergeOthers(values, utils, meta); + return mergeOthers(values, utils, meta); } } /** @@ -166,6 +175,84 @@ function mergeUnknowns(values, utils, meta) { * @param values - The records. */ function mergeRecords(values, utils, meta) { + const result = utils.mergeFunctions.mergeRecords(values, utils, meta); + if (result === actions.defaultMerge || + (utils.useImplicitDefaultMerging && + result === undefined && + utils.mergeFunctions.mergeRecords !== + utils.defaultMergeFunctions.mergeRecords)) { + return utils.defaultMergeFunctions.mergeRecords(values, utils, meta); + } + return result; +} +/** + * Merge arrays. + * + * @param values - The arrays. + */ +function mergeArrays(values, utils, meta) { + const result = utils.mergeFunctions.mergeArrays(values, utils, meta); + if (result === actions.defaultMerge || + (utils.useImplicitDefaultMerging && + result === undefined && + utils.mergeFunctions.mergeArrays !== + utils.defaultMergeFunctions.mergeArrays)) { + return utils.defaultMergeFunctions.mergeArrays(values); + } + return result; +} +/** + * Merge sets. + * + * @param values - The sets. + */ +function mergeSets(values, utils, meta) { + const result = utils.mergeFunctions.mergeSets(values, utils, meta); + if (result === actions.defaultMerge || + (utils.useImplicitDefaultMerging && + result === undefined && + utils.mergeFunctions.mergeSets !== utils.defaultMergeFunctions.mergeSets)) { + return utils.defaultMergeFunctions.mergeSets(values); + } + return result; +} +/** + * Merge maps. + * + * @param values - The maps. + */ +function mergeMaps(values, utils, meta) { + const result = utils.mergeFunctions.mergeMaps(values, utils, meta); + if (result === actions.defaultMerge || + (utils.useImplicitDefaultMerging && + result === undefined && + utils.mergeFunctions.mergeMaps !== utils.defaultMergeFunctions.mergeMaps)) { + return utils.defaultMergeFunctions.mergeMaps(values); + } + return result; +} +/** + * Merge other things. + * + * @param values - The other things. + */ +function mergeOthers(values, utils, meta) { + const result = utils.mergeFunctions.mergeOthers(values, utils, meta); + if (result === actions.defaultMerge || + (utils.useImplicitDefaultMerging && + result === undefined && + utils.mergeFunctions.mergeOthers !== + utils.defaultMergeFunctions.mergeOthers)) { + return utils.defaultMergeFunctions.mergeOthers(values); + } + return result; +} +/** + * The default strategy to merge records. + * + * @param values - The records. + */ +function defaultMergeRecords(values, utils, meta) { const result = {}; /* eslint-disable functional/no-loop-statement, functional/no-conditional-statement -- using a loop here is more performant. */ for (const key of getKeys(values)) { @@ -180,39 +267,41 @@ function mergeRecords(values, utils, meta) { key, parents: values, }); - result[key] = mergeUnknowns(propValues, utils, updatedMeta); + const propertyResult = mergeUnknowns(propValues, utils, updatedMeta); + if (propertyResult === actions.skip) { + continue; + } + result[key] = propertyResult; } /* eslint-enable functional/no-loop-statement, functional/no-conditional-statement */ return result; } /** - * Merge arrays. + * The default strategy to merge arrays. * * @param values - The arrays. */ -function mergeArrays(values) { +function defaultMergeArrays(values) { return values.flat(); } /** - * Merge sets. + * The default strategy to merge sets. * * @param values - The sets. */ -function mergeSets(values) { +function defaultMergeSets(values) { return new Set(getIterableOfIterables(values)); } /** - * Merge maps. + * The default strategy to merge maps. * * @param values - The maps. */ -function mergeMaps(values) { +function defaultMergeMaps(values) { return new Map(getIterableOfIterables(values)); } /** - * Merge "other" things. - * - * @param values - The values. + * Get the last value in the given array. */ function leaf(values) { return values[values.length - 1]; diff --git a/dist/node/types/current/index.d.ts b/dist/node/types/current/index.d.ts index dd3c7d5a..ef9b9f63 100644 --- a/dist/node/types/current/index.d.ts +++ b/dist/node/types/current/index.d.ts @@ -306,23 +306,24 @@ declare type GetDeepMergeMergeFunctionsURIs = DeepMergeBuiltInMetaData> = Partial>>; -declare type MetaDataUpdater> = (previousMeta: M | undefined, metaMeta: MM) => M; +declare type DeepMergeOptions> = DeepMergeBuiltInMetaData> = Partial>; +declare type MetaDataUpdater = (previousMeta: M | undefined, metaMeta: Readonly>) => M; /** * All the options the user can pass to customize deepmerge. */ -declare type DeepMergeOptionsFull> = Readonly<{ +declare type DeepMergeOptionsFull = Readonly<{ mergeRecords: DeepMergeMergeFunctions["mergeRecords"] | false; mergeArrays: DeepMergeMergeFunctions["mergeArrays"] | false; mergeMaps: DeepMergeMergeFunctions["mergeMaps"] | false; mergeSets: DeepMergeMergeFunctions["mergeSets"] | false; mergeOthers: DeepMergeMergeFunctions["mergeOthers"]; metaDataUpdater: MetaDataUpdater; + enableImplicitDefaultMerging: boolean; }>; /** * All the merge functions that deepmerge uses. */ -declare type DeepMergeMergeFunctions> = Readonly<{ +declare type DeepMergeMergeFunctions = Readonly<{ mergeRecords: >>, U extends DeepMergeMergeFunctionUtils>(records: Ts, utils: U, meta: M | undefined) => unknown; mergeArrays: >, U extends DeepMergeMergeFunctionUtils>(records: Ts, utils: U, meta: M | undefined) => unknown; mergeMaps: >>, U extends DeepMergeMergeFunctionUtils>(records: Ts, utils: U, meta: M | undefined) => unknown; @@ -332,18 +333,23 @@ declare type DeepMergeMergeFunctions> /** * The utils provided to the merge functions. */ -declare type DeepMergeMergeFunctionUtils> = Readonly<{ +declare type DeepMergeMergeFunctionUtils = Readonly<{ mergeFunctions: DeepMergeMergeFunctions; defaultMergeFunctions: DeepMergeMergeFunctionsDefaults; metaDataUpdater: MetaDataUpdater; deepmerge: >(...values: Ts) => unknown; + useImplicitDefaultMerging: boolean; + actions: Readonly<{ + defaultMerge: symbol; + skip: symbol; + }>; }>; declare const defaultMergeFunctions: { - readonly mergeMaps: typeof mergeMaps; - readonly mergeSets: typeof mergeSets; - readonly mergeArrays: typeof mergeArrays; - readonly mergeRecords: typeof mergeRecords; + readonly mergeMaps: typeof defaultMergeMaps; + readonly mergeSets: typeof defaultMergeSets; + readonly mergeArrays: typeof defaultMergeArrays; + readonly mergeRecords: typeof defaultMergeRecords; readonly mergeOthers: typeof leaf; }; /** @@ -368,35 +374,33 @@ declare function deepmergeCustom, MetaData, MetaMetaData extends Readonly> = DeepMergeBuiltInMetaData>(options: DeepMergeOptions, rootMetaData?: MetaData): >(...objects: Ts) => DeepMergeHKT, MetaData>; +declare function deepmergeCustom, MetaData, MetaMetaData extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData>(options: DeepMergeOptions, rootMetaData?: MetaData): >(...objects: Ts) => DeepMergeHKT, MetaData>; /** - * Merge records. + * The default strategy to merge records. * * @param values - The records. */ -declare function mergeRecords>, U extends DeepMergeMergeFunctionUtils, MF extends DeepMergeMergeFunctionsURIs, M, MM extends DeepMergeBuiltInMetaData>(values: Ts, utils: U, meta: M | undefined): DeepMergeRecordsDefaultHKT; +declare function defaultMergeRecords>, U extends DeepMergeMergeFunctionUtils, MF extends DeepMergeMergeFunctionsURIs, M, MM extends DeepMergeBuiltInMetaData>(values: Ts, utils: U, meta: M | undefined): DeepMergeRecordsDefaultHKT; /** - * Merge arrays. + * The default strategy to merge arrays. * * @param values - The arrays. */ -declare function mergeArrays>, MF extends DeepMergeMergeFunctionsURIs, M>(values: Ts): Ts extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? any : [...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head] : never : never : [...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head] : never : never : [...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head] : never : never : [...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head] : never : never : [...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head] : never : never : [...Head, ...Head, ...Head, ...Head, ...Head, ...Head] : never : never : [...Head, ...Head, ...Head, ...Head, ...Head] : never : never : [...Head, ...Head, ...Head, ...Head] : never : never : [...Head, ...Head, ...Head] : never : never : [...Head, ...Head] : never : never : [...Head] : never : never; +declare function defaultMergeArrays>, MF extends DeepMergeMergeFunctionsURIs, M>(values: Ts): Ts extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? Rest extends readonly [infer Head, ...infer Rest] ? Head extends readonly unknown[] ? Rest extends readonly [readonly unknown[], ...(readonly unknown[])[]] ? any : [...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head] : never : never : [...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head] : never : never : [...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head] : never : never : [...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head] : never : never : [...Head, ...Head, ...Head, ...Head, ...Head, ...Head, ...Head] : never : never : [...Head, ...Head, ...Head, ...Head, ...Head, ...Head] : never : never : [...Head, ...Head, ...Head, ...Head, ...Head] : never : never : [...Head, ...Head, ...Head, ...Head] : never : never : [...Head, ...Head, ...Head] : never : never : [...Head, ...Head] : never : never : [...Head] : never : never; /** - * Merge sets. + * The default strategy to merge sets. * * @param values - The sets. */ -declare function mergeSets>>>(values: Ts): DeepMergeSetsDefaultHKT; +declare function defaultMergeSets>>>(values: Ts): DeepMergeSetsDefaultHKT; /** - * Merge maps. + * The default strategy to merge maps. * * @param values - The maps. */ -declare function mergeMaps>>>(values: Ts): DeepMergeMapsDefaultHKT; +declare function defaultMergeMaps>>>(values: Ts): DeepMergeMapsDefaultHKT; /** - * Merge "other" things. - * - * @param values - The values. + * Get the last value in the given array. */ declare function leaf>(values: Ts): unknown;