diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ffe64be..e5c18240 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,26 @@ # Changelog All notable changes to this project will be documented in this file. Dates are displayed in UTC. +# [7.0.0](https://github.com/RebeccaStevens/deepmerge-ts/compare/v6.0.3...v7.0.0) (2024-05-20) + + +### Code Refactoring + +* rename DeepMergeFunctionUtils to DeepMergeUtils ([e821255](https://github.com/RebeccaStevens/deepmerge-ts/commit/e821255380dd9307041e6749c43d363e4e2ae633)) +* rename DeepMergeMerge* to DeepMerge* ([fd4d2d4](https://github.com/RebeccaStevens/deepmerge-ts/commit/fd4d2d462eec14841adc45d741148cc7a9449a1f)) + + +### Features + +* allow filtering out values before merging them ([0784f63](https://github.com/RebeccaStevens/deepmerge-ts/commit/0784f63befc4ab4d66b6f3ae4b2076fba203fb48)), closes [#460](https://github.com/RebeccaStevens/deepmerge-ts/issues/460) + + +### BREAKING CHANGES + +* rename DeepMergeFunctionUtils to DeepMergeUtils +* rename DeepMergeMerge* to DeepMerge* +* allow filtering out values before merging them + ## [6.0.3](https://github.com/RebeccaStevens/deepmerge-ts/compare/v6.0.2...v6.0.3) (2024-05-20) diff --git a/dist/deno/deepmerge-into.ts b/dist/deno/deepmerge-into.ts index bfd119cc..b822bf90 100644 --- a/dist/deno/deepmerge-into.ts +++ b/dist/deno/deepmerge-into.ts @@ -1,12 +1,15 @@ import { actionsInto as actions } from "./actions.ts"; +import { + defaultFilterValues, + defaultMetaDataUpdater, +} from "./defaults/general.ts"; import * as defaultMergeIntoFunctions from "./defaults/into.ts"; -import { defaultMetaDataUpdater } from "./defaults/meta-data-updater.ts"; import { type DeepMergeBuiltInMetaData, + type DeepMergeFunctionsDefaultURIs, type DeepMergeHKT, + type DeepMergeIntoFunctionUtils, type DeepMergeIntoOptions, - type DeepMergeMergeFunctionsDefaultURIs, - type DeepMergeMergeIntoFunctionUtils, type Reference, } from "./types/index.ts"; import { type SimplifyObject } from "./types/utils.ts"; @@ -39,7 +42,7 @@ export function deepmergeInto< Target & DeepMergeHKT< [Target, ...Ts], - DeepMergeMergeFunctionsDefaultURIs, + DeepMergeFunctionsDefaultURIs, DeepMergeBuiltInMetaData > >; @@ -54,7 +57,7 @@ export function deepmergeInto< Target & DeepMergeHKT< [Target, ...Ts], - DeepMergeMergeFunctionsDefaultURIs, + DeepMergeFunctionsDefaultURIs, DeepMergeBuiltInMetaData > > { @@ -116,7 +119,7 @@ export function deepmergeIntoCustom< ...objects: Ts ) => void; - const utils: DeepMergeMergeIntoFunctionUtils = + const utils: DeepMergeIntoFunctionUtils = getIntoUtils(options, customizedDeepmergeInto as CustomizedDeepmergeInto); /** @@ -147,11 +150,8 @@ function getIntoUtils< MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( options: DeepMergeIntoOptions, - customizedDeepmergeInto: DeepMergeMergeIntoFunctionUtils< - M, - MM - >["deepmergeInto"], -): DeepMergeMergeIntoFunctionUtils { + customizedDeepmergeInto: DeepMergeIntoFunctionUtils["deepmergeInto"], +): DeepMergeIntoFunctionUtils { return { defaultMergeFunctions: defaultMergeIntoFunctions, mergeFunctions: { @@ -167,13 +167,17 @@ function getIntoUtils< : [key, option], ), ), - } as DeepMergeMergeIntoFunctionUtils["mergeFunctions"], + } as DeepMergeIntoFunctionUtils["mergeFunctions"], metaDataUpdater: (options.metaDataUpdater ?? - defaultMetaDataUpdater) as unknown as DeepMergeMergeIntoFunctionUtils< + defaultMetaDataUpdater) as unknown as DeepMergeIntoFunctionUtils< M, MM >["metaDataUpdater"], deepmergeInto: customizedDeepmergeInto, + filterValues: + options.filterValues === false + ? undefined + : options.filterValues ?? defaultFilterValues, actions, }; } @@ -186,7 +190,7 @@ function getIntoUtils< */ export function mergeUnknownsInto< Ts extends ReadonlyArray, - U extends DeepMergeMergeIntoFunctionUtils, + U extends DeepMergeIntoFunctionUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( @@ -196,22 +200,34 @@ export function mergeUnknownsInto< meta: M | undefined, // eslint-disable-next-line ts/no-invalid-void-type ): void | symbol { - if (values.length === 0) { + const filteredValues = utils.filterValues?.(values, meta) ?? values; + + if (filteredValues.length === 0) { return; } - if (values.length === 1) { - return void mergeOthersInto(m_target, values, utils, meta); + if (filteredValues.length === 1) { + return void mergeOthersInto( + m_target, + filteredValues, + utils, + meta, + ); } const type = getObjectType(m_target.value); if (type !== ObjectType.NOT && type !== ObjectType.OTHER) { - for (let m_index = 1; m_index < values.length; m_index++) { - if (getObjectType(values[m_index]) === type) { + for (let m_index = 1; m_index < filteredValues.length; m_index++) { + if (getObjectType(filteredValues[m_index]) === type) { continue; } - return void mergeOthersInto(m_target, values, utils, meta); + return void mergeOthersInto( + m_target, + filteredValues, + utils, + meta, + ); } } @@ -219,7 +235,7 @@ export function mergeUnknownsInto< case ObjectType.RECORD: { return void mergeRecordsInto( m_target as Reference>, - values as ReadonlyArray>>, + filteredValues as ReadonlyArray>>, utils, meta, ); @@ -228,7 +244,7 @@ export function mergeUnknownsInto< case ObjectType.ARRAY: { return void mergeArraysInto( m_target as Reference, - values as ReadonlyArray>, + filteredValues as ReadonlyArray>, utils, meta, ); @@ -237,7 +253,7 @@ export function mergeUnknownsInto< case ObjectType.SET: { return void mergeSetsInto( m_target as Reference>, - values as ReadonlyArray>>, + filteredValues as ReadonlyArray>>, utils, meta, ); @@ -246,14 +262,21 @@ export function mergeUnknownsInto< case ObjectType.MAP: { return void mergeMapsInto( m_target as Reference>, - values as ReadonlyArray>>, + filteredValues as ReadonlyArray< + Readonly> + >, utils, meta, ); } default: { - return void mergeOthersInto(m_target, values, utils, meta); + return void mergeOthersInto( + m_target, + filteredValues, + utils, + meta, + ); } } } @@ -265,7 +288,7 @@ export function mergeUnknownsInto< * @param values - The records. */ function mergeRecordsInto< - U extends DeepMergeMergeIntoFunctionUtils, + U extends DeepMergeIntoFunctionUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( @@ -298,7 +321,7 @@ function mergeRecordsInto< * @param values - The arrays. */ function mergeArraysInto< - U extends DeepMergeMergeIntoFunctionUtils, + U extends DeepMergeIntoFunctionUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( @@ -326,7 +349,7 @@ function mergeArraysInto< * @param values - The sets. */ function mergeSetsInto< - U extends DeepMergeMergeIntoFunctionUtils, + U extends DeepMergeIntoFunctionUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( @@ -349,7 +372,7 @@ function mergeSetsInto< * @param values - The maps. */ function mergeMapsInto< - U extends DeepMergeMergeIntoFunctionUtils, + U extends DeepMergeIntoFunctionUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( @@ -372,7 +395,7 @@ function mergeMapsInto< * @param values - The other things. */ function mergeOthersInto< - U extends DeepMergeMergeIntoFunctionUtils, + U extends DeepMergeIntoFunctionUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( diff --git a/dist/deno/deepmerge.ts b/dist/deno/deepmerge.ts index ceeff141..f4d39983 100644 --- a/dist/deno/deepmerge.ts +++ b/dist/deno/deepmerge.ts @@ -1,14 +1,17 @@ import { actions } from "./actions.ts"; -import { defaultMetaDataUpdater } from "./defaults/meta-data-updater.ts"; +import { + defaultFilterValues, + defaultMetaDataUpdater, +} from "./defaults/general.ts"; import * as defaultMergeFunctions from "./defaults/vanilla.ts"; import { type DeepMergeBuiltInMetaData, + type DeepMergeFunctionsDefaultURIs, + type DeepMergeFunctionsURIs, type DeepMergeHKT, - type DeepMergeMergeFunctionUtils, - type DeepMergeMergeFunctionsDefaultURIs, - type DeepMergeMergeFunctionsURIs, type DeepMergeOptions, - type GetDeepMergeMergeFunctionsURIs, + type DeepMergeUtils, + type GetDeepMergeFunctionsURIs, } from "./types/index.ts"; import { ObjectType, getObjectType } from "./utils.ts"; @@ -19,14 +22,10 @@ import { ObjectType, getObjectType } from "./utils.ts"; */ export function deepmerge>>( ...objects: readonly [...Ts] -): DeepMergeHKT< - Ts, - DeepMergeMergeFunctionsDefaultURIs, - DeepMergeBuiltInMetaData -> { +): DeepMergeHKT { return deepmergeCustom({})(...objects) as DeepMergeHKT< Ts, - DeepMergeMergeFunctionsDefaultURIs, + DeepMergeFunctionsDefaultURIs, DeepMergeBuiltInMetaData >; } @@ -38,16 +37,12 @@ export function deepmerge>>( */ export function deepmergeCustom< BaseTs = unknown, - PMF extends Partial = {}, + PMF extends Partial = {}, >( options: DeepMergeOptions, ): >( ...objects: Ts -) => DeepMergeHKT< - Ts, - GetDeepMergeMergeFunctionsURIs, - DeepMergeBuiltInMetaData ->; +) => DeepMergeHKT, DeepMergeBuiltInMetaData>; /** * Deeply merge two or more objects using the given options and meta data. @@ -57,7 +52,7 @@ export function deepmergeCustom< */ export function deepmergeCustom< BaseTs = unknown, - PMF extends Partial = {}, + PMF extends Partial = {}, MetaData = DeepMergeBuiltInMetaData, MetaMetaData extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( @@ -65,11 +60,11 @@ export function deepmergeCustom< rootMetaData?: MetaData, ): >( ...objects: Ts -) => DeepMergeHKT, MetaData>; +) => DeepMergeHKT, MetaData>; export function deepmergeCustom< BaseTs, - PMF extends Partial, + PMF extends Partial, MetaData, MetaMetaData extends DeepMergeBuiltInMetaData, >( @@ -77,15 +72,15 @@ export function deepmergeCustom< rootMetaData?: MetaData, ): >( ...objects: Ts -) => DeepMergeHKT, MetaData> { +) => DeepMergeHKT, MetaData> { /** * The type of the customized deepmerge function. */ type CustomizedDeepmerge = >( ...objects: Ts - ) => DeepMergeHKT, MetaData>; + ) => DeepMergeHKT, MetaData>; - const utils: DeepMergeMergeFunctionUtils = getUtils( + const utils: DeepMergeUtils = getUtils( options, customizedDeepmerge as CustomizedDeepmerge, ); @@ -97,7 +92,7 @@ export function deepmergeCustom< return mergeUnknowns< ReadonlyArray, typeof utils, - GetDeepMergeMergeFunctionsURIs, + GetDeepMergeFunctionsURIs, MetaData, MetaMetaData >(objects, utils, rootMetaData); @@ -116,8 +111,8 @@ function getUtils< MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( options: DeepMergeOptions, - customizedDeepmerge: DeepMergeMergeFunctionUtils["deepmerge"], -): DeepMergeMergeFunctionUtils { + customizedDeepmerge: DeepMergeUtils["deepmerge"], +): DeepMergeUtils { return { defaultMergeFunctions, mergeFunctions: { @@ -131,14 +126,18 @@ function getUtils< : [key, option], ), ), - } as DeepMergeMergeFunctionUtils["mergeFunctions"], + } as DeepMergeUtils["mergeFunctions"], metaDataUpdater: (options.metaDataUpdater ?? - defaultMetaDataUpdater) as unknown as DeepMergeMergeFunctionUtils< + defaultMetaDataUpdater) as unknown as DeepMergeUtils< M, MM >["metaDataUpdater"], deepmerge: customizedDeepmerge, useImplicitDefaultMerging: options.enableImplicitDefaultMerging ?? false, + filterValues: + options.filterValues === false + ? undefined + : options.filterValues ?? defaultFilterValues, actions, }; } @@ -150,33 +149,35 @@ function getUtils< */ export function mergeUnknowns< Ts extends ReadonlyArray, - U extends DeepMergeMergeFunctionUtils, - MF extends DeepMergeMergeFunctionsURIs, + U extends DeepMergeUtils, + Fs extends DeepMergeFunctionsURIs, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, ->(values: Ts, utils: U, meta: M | undefined): DeepMergeHKT { - if (values.length === 0) { - return undefined as DeepMergeHKT; +>(values: Ts, utils: U, meta: M | undefined): DeepMergeHKT { + const filteredValues = utils.filterValues?.(values, meta) ?? values; + + if (filteredValues.length === 0) { + return undefined as DeepMergeHKT; } - if (values.length === 1) { - return mergeOthers(values, utils, meta) as DeepMergeHKT< + if (filteredValues.length === 1) { + return mergeOthers(filteredValues, utils, meta) as DeepMergeHKT< Ts, - MF, + Fs, M >; } - const type = getObjectType(values[0]); + const type = getObjectType(filteredValues[0]); if (type !== ObjectType.NOT && type !== ObjectType.OTHER) { - for (let m_index = 1; m_index < values.length; m_index++) { - if (getObjectType(values[m_index]) === type) { + for (let m_index = 1; m_index < filteredValues.length; m_index++) { + if (getObjectType(filteredValues[m_index]) === type) { continue; } - return mergeOthers(values, utils, meta) as DeepMergeHKT< + return mergeOthers(filteredValues, utils, meta) as DeepMergeHKT< Ts, - MF, + Fs, M >; } @@ -184,41 +185,43 @@ export function mergeUnknowns< switch (type) { case ObjectType.RECORD: { - return mergeRecords( - values as ReadonlyArray>>, + return mergeRecords( + filteredValues as ReadonlyArray>>, utils, meta, - ) as DeepMergeHKT; + ) as DeepMergeHKT; } case ObjectType.ARRAY: { return mergeArrays( - values as ReadonlyArray>>, + filteredValues as ReadonlyArray>>, utils, meta, - ) as DeepMergeHKT; + ) as DeepMergeHKT; } case ObjectType.SET: { return mergeSets( - values as ReadonlyArray>>, + filteredValues as ReadonlyArray>>, utils, meta, - ) as DeepMergeHKT; + ) as DeepMergeHKT; } case ObjectType.MAP: { return mergeMaps( - values as ReadonlyArray>>, + filteredValues as ReadonlyArray< + Readonly> + >, utils, meta, - ) as DeepMergeHKT; + ) as DeepMergeHKT; } default: { - return mergeOthers(values, utils, meta) as DeepMergeHKT< + return mergeOthers(filteredValues, utils, meta) as DeepMergeHKT< Ts, - MF, + Fs, M >; } @@ -231,8 +234,8 @@ export function mergeUnknowns< * @param values - The records. */ function mergeRecords< - U extends DeepMergeMergeFunctionUtils, - MF extends DeepMergeMergeFunctionsURIs, + U extends DeepMergeUtils, + Fs extends DeepMergeFunctionsURIs, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( @@ -252,7 +255,7 @@ function mergeRecords< return utils.defaultMergeFunctions.mergeRecords< ReadonlyArray>>, U, - MF, + Fs, M, MM >(values, utils, meta); @@ -267,7 +270,7 @@ function mergeRecords< * @param values - The arrays. */ function mergeArrays< - U extends DeepMergeMergeFunctionUtils, + U extends DeepMergeUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( @@ -295,7 +298,7 @@ function mergeArrays< * @param values - The sets. */ function mergeSets< - U extends DeepMergeMergeFunctionUtils, + U extends DeepMergeUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( @@ -322,7 +325,7 @@ function mergeSets< * @param values - The maps. */ function mergeMaps< - U extends DeepMergeMergeFunctionUtils, + U extends DeepMergeUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( @@ -349,7 +352,7 @@ function mergeMaps< * @param values - The other things. */ function mergeOthers< - U extends DeepMergeMergeFunctionUtils, + U extends DeepMergeUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >(values: ReadonlyArray, utils: U, meta: M | undefined) { diff --git a/dist/deno/defaults/general.ts b/dist/deno/defaults/general.ts new file mode 100644 index 00000000..a9f44722 --- /dev/null +++ b/dist/deno/defaults/general.ts @@ -0,0 +1,25 @@ +import { type DeepMergeBuiltInMetaData } from "../types/index.ts"; + +/** + * The default function to update meta data. + * + * It doesn't update the meta data. + */ +export function defaultMetaDataUpdater( + previousMeta: M, + metaMeta: DeepMergeBuiltInMetaData, +): DeepMergeBuiltInMetaData { + return metaMeta; +} + +/** + * The default function to filter values. + * + * It filters out undefined values. + */ +export function defaultFilterValues, M>( + values: Ts, + meta: M | undefined, +): unknown[] { + return values.filter((value) => value !== undefined); +} diff --git a/dist/deno/defaults/into.ts b/dist/deno/defaults/into.ts index b32fd976..65ae1a9a 100644 --- a/dist/deno/defaults/into.ts +++ b/dist/deno/defaults/into.ts @@ -1,7 +1,7 @@ import { mergeUnknownsInto } from "../deepmerge-into.ts"; import { type DeepMergeBuiltInMetaData, - type DeepMergeMergeIntoFunctionUtils, + type DeepMergeIntoFunctionUtils, type Reference, } from "../types/index.ts"; import { getIterableOfIterables, getKeys, objectHasProperty } from "../utils.ts"; @@ -25,7 +25,7 @@ export type MergeFunctions = { */ export function mergeRecords< Ts extends ReadonlyArray>, - U extends DeepMergeMergeIntoFunctionUtils, + U extends DeepMergeIntoFunctionUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( @@ -121,11 +121,5 @@ export function mergeOthers>( m_target: Reference, values: Ts, ) { - for (let i = values.length - 1; i >= 0; i--) { - if (values[i] !== undefined) { - m_target.value = values[i]; - return; - } - } - m_target.value = undefined; + m_target.value = values.at(-1); } diff --git a/dist/deno/defaults/meta-data-updater.ts b/dist/deno/defaults/meta-data-updater.ts deleted file mode 100644 index 1b9432c3..00000000 --- a/dist/deno/defaults/meta-data-updater.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { type DeepMergeBuiltInMetaData } from "../types/index.ts"; - -/** - * The default function to update meta data. - */ -export function defaultMetaDataUpdater( - previousMeta: M, - metaMeta: DeepMergeBuiltInMetaData, -): DeepMergeBuiltInMetaData { - return metaMeta; -} diff --git a/dist/deno/defaults/vanilla.ts b/dist/deno/defaults/vanilla.ts index decd60cd..a3bd2d60 100644 --- a/dist/deno/defaults/vanilla.ts +++ b/dist/deno/defaults/vanilla.ts @@ -3,11 +3,11 @@ import { mergeUnknowns } from "../deepmerge.ts"; import { type DeepMergeArraysDefaultHKT, type DeepMergeBuiltInMetaData, + type DeepMergeFunctionsURIs, type DeepMergeMapsDefaultHKT, - type DeepMergeMergeFunctionUtils, - type DeepMergeMergeFunctionsURIs, type DeepMergeRecordsDefaultHKT, type DeepMergeSetsDefaultHKT, + type DeepMergeUtils, } from "../types/index.ts"; import { getIterableOfIterables, getKeys, objectHasProperty } from "../utils.ts"; @@ -29,15 +29,15 @@ export type MergeFunctions = { */ export function mergeRecords< Ts extends ReadonlyArray>, - U extends DeepMergeMergeFunctionUtils, - MF extends DeepMergeMergeFunctionsURIs, + U extends DeepMergeUtils, + Fs extends DeepMergeFunctionsURIs, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( values: Ts, utils: U, meta: M | undefined, -): DeepMergeRecordsDefaultHKT { +): DeepMergeRecordsDefaultHKT { const result: Record = {}; for (const key of getKeys(values)) { @@ -58,7 +58,7 @@ export function mergeRecords< parents: values, } as unknown as MM); - const propertyResult = mergeUnknowns, U, MF, M, MM>( + const propertyResult = mergeUnknowns, U, Fs, M, MM>( propValues, utils, updatedMeta, @@ -80,7 +80,7 @@ export function mergeRecords< } } - return result as DeepMergeRecordsDefaultHKT; + return result as DeepMergeRecordsDefaultHKT; } /** @@ -90,10 +90,10 @@ export function mergeRecords< */ export function mergeArrays< Ts extends ReadonlyArray>, - MF extends DeepMergeMergeFunctionsURIs, + Fs extends DeepMergeFunctionsURIs, M, ->(values: Ts): DeepMergeArraysDefaultHKT { - return values.flat() as DeepMergeArraysDefaultHKT; +>(values: Ts): DeepMergeArraysDefaultHKT { + return values.flat() as DeepMergeArraysDefaultHKT; } /** @@ -122,10 +122,5 @@ export function mergeMaps< * Get the last non-undefined value in the given array. */ export function mergeOthers>(values: Ts) { - for (let i = values.length - 1; i >= 0; i--) { - if (values[i] !== undefined) { - return values[i]; - } - } - return undefined; + return values.at(-1); } diff --git a/dist/deno/index.ts b/dist/deno/index.ts index cd408d1a..60bf4c05 100644 --- a/dist/deno/index.ts +++ b/dist/deno/index.ts @@ -7,24 +7,26 @@ export { objectHasProperty, } from "./utils.ts"; -export type { MergeFunctions as DeepMergeMergeIntoFunctionsDefaults } from "./defaults/into.ts"; -export type { MergeFunctions as DeepMergeMergeFunctionsDefaults } from "./defaults/vanilla.ts"; +export type { MergeFunctions as DeepMergeIntoFunctionsDefaults } from "./defaults/into.ts"; +export type { MergeFunctions as DeepMergeFunctionsDefaults } from "./defaults/vanilla.ts"; export type { DeepMergeArraysDefaultHKT, DeepMergeBuiltInMetaData, DeepMergeHKT, DeepMergeLeaf, DeepMergeLeafURI, + DeepMergeNoFilteringURI, DeepMergeMapsDefaultHKT, - DeepMergeMergeFunctionsDefaultURIs, - DeepMergeMergeFunctionsURIs, - DeepMergeMergeFunctionURItoKind, - DeepMergeMergeFunctionUtils, - DeepMergeMergeIntoFunctionUtils, + DeepMergeFunctionsDefaultURIs, + DeepMergeFunctionsURIs, + DeepMergeFunctionURItoKind, + DeepMergeUtils, + DeepMergeIntoFunctionUtils, DeepMergeOptions, DeepMergeIntoOptions, DeepMergeRecordsDefaultHKT, DeepMergeSetsDefaultHKT, Reference as DeepMergeValueReference, - GetDeepMergeMergeFunctionsURIs, + GetDeepMergeFunctionsURIs, } from "./types/index.ts"; +export type { FilterOut } from "./types/utils.ts"; diff --git a/dist/deno/types/defaults.ts b/dist/deno/types/defaults.ts index aaa389e8..a8096baa 100644 --- a/dist/deno/types/defaults.ts +++ b/dist/deno/types/defaults.ts @@ -1,10 +1,11 @@ import { + type DeepMergeFunctionURItoKind, + type DeepMergeFunctionsURIs, type DeepMergeHKT, type DeepMergeLeafURI, - type DeepMergeMergeFunctionURItoKind, - type DeepMergeMergeFunctionsURIs, } from "./merging.ts"; import { + type FilterOut, type FilterOutNever, type FlattenTuples, type KeyIsOptional, @@ -37,15 +38,21 @@ type DeepMergeSetsDefaultURI = "DeepMergeSetsDefaultURI"; */ type DeepMergeMapsDefaultURI = "DeepMergeMapsDefaultURI"; +/** + * The default filter values function. + */ +type DeepMergeFilterValuesDefaultURI = "DeepMergeFilterValuesDefaultURI"; + /** * The default merge functions to use when deep merging. */ -export type DeepMergeMergeFunctionsDefaultURIs = Readonly<{ +export type DeepMergeFunctionsDefaultURIs = Readonly<{ DeepMergeRecordsURI: DeepMergeRecordsDefaultURI; DeepMergeArraysURI: DeepMergeArraysDefaultURI; DeepMergeSetsURI: DeepMergeSetsDefaultURI; DeepMergeMapsURI: DeepMergeMapsDefaultURI; DeepMergeOthersURI: DeepMergeLeafURI; + DeepMergeFilterValuesURI: DeepMergeFilterValuesDefaultURI; }>; type RecordEntries> = TuplifyUnion< @@ -88,12 +95,12 @@ type RecordToRecordMeta> = */ export type DeepMergeRecordsDefaultHKT< Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs, + Fs extends DeepMergeFunctionsURIs, M, > = Ts extends ReadonlyArray> ? SimplifyObject< - DeepMergeRecordMetaDefaultHKTProps, MF, M> + DeepMergeRecordMetaDefaultHKTProps, Fs, M> > : never; @@ -102,11 +109,11 @@ export type DeepMergeRecordsDefaultHKT< */ type DeepMergeRecordMetaDefaultHKTProps< RecordMetas, - MF extends DeepMergeMergeFunctionsURIs, + Fs extends DeepMergeFunctionsURIs, M, > = RecordMetas extends ReadonlyArray - ? CreateRecordFromMeta, MF, M> + ? CreateRecordFromMeta, Fs, M> : never; type MergeRecordMeta> = @@ -136,7 +143,7 @@ type GroupValuesByKey = Ts extends readonly [ } : never; -type CreateRecordFromMeta = +type CreateRecordFromMeta = Ts extends ReadonlyArray ? TupleToIntersection<{ [I in keyof Ts]: Ts[I] extends { @@ -144,7 +151,7 @@ type CreateRecordFromMeta = values: infer Values extends ReadonlyArray; optional: infer O extends boolean; } - ? CreateRecordForKeyFromMeta + ? CreateRecordForKeyFromMeta : never; }> : never; @@ -153,14 +160,14 @@ type CreateRecordForKeyFromMeta< Key extends PropertyKey, Values extends ReadonlyArray, Optional extends boolean, - MF extends DeepMergeMergeFunctionsURIs, + Fs extends DeepMergeFunctionsURIs, M, > = Optional extends true ? { - [k in Key]+?: DeepMergeHKT; + [k in Key]+?: DeepMergeHKT; } : { - [k in Key]-?: DeepMergeHKT; + [k in Key]-?: DeepMergeHKT; }; /** @@ -260,16 +267,16 @@ type DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper< */ export type DeepMergeArraysDefaultHKT< Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs, + Fs extends DeepMergeFunctionsURIs, M, -> = DeepMergeArraysDefaultHKTHelper; +> = DeepMergeArraysDefaultHKTHelper; /** * Tail-recursive helper type for DeepMergeArraysDefaultHKT. */ type DeepMergeArraysDefaultHKTHelper< Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs, + Fs extends DeepMergeFunctionsURIs, M, Acc extends ReadonlyArray, > = Ts extends readonly [ @@ -280,7 +287,7 @@ type DeepMergeArraysDefaultHKTHelper< ReadonlyArray, ...ReadonlyArray>, ] - ? DeepMergeArraysDefaultHKTHelper + ? DeepMergeArraysDefaultHKTHelper : [...Acc, ...Head] : never; @@ -299,39 +306,51 @@ export type DeepMergeMapsDefaultHKT> = Map< UnionMapValues >; +/** + * Filter out undefined values. + */ +export type DeepMergeFilterValuesDefaultHKT> = + FilterOut; + /** * Get the merge functions with defaults apply from the given subset. */ -export type GetDeepMergeMergeFunctionsURIs< - PMF extends Partial, +export type GetDeepMergeFunctionsURIs< + PMF extends Partial, > = Readonly<{ // prettier-ignore DeepMergeRecordsURI: - PMF["DeepMergeRecordsURI"] extends keyof DeepMergeMergeFunctionURItoKind + PMF["DeepMergeRecordsURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeRecordsURI"] : DeepMergeRecordsDefaultURI; // prettier-ignore DeepMergeArraysURI: - PMF["DeepMergeArraysURI"] extends keyof DeepMergeMergeFunctionURItoKind + PMF["DeepMergeArraysURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeArraysURI"] : DeepMergeArraysDefaultURI; // prettier-ignore DeepMergeSetsURI: - PMF["DeepMergeSetsURI"] extends keyof DeepMergeMergeFunctionURItoKind + PMF["DeepMergeSetsURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeSetsURI"] : DeepMergeSetsDefaultURI; // prettier-ignore DeepMergeMapsURI: - PMF["DeepMergeMapsURI"] extends keyof DeepMergeMergeFunctionURItoKind + PMF["DeepMergeMapsURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeMapsURI"] : DeepMergeMapsDefaultURI; // prettier-ignore DeepMergeOthersURI: - PMF["DeepMergeOthersURI"] extends keyof DeepMergeMergeFunctionURItoKind + PMF["DeepMergeOthersURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeOthersURI"] : DeepMergeLeafURI; + + // prettier-ignore + DeepMergeFilterValuesURI: + PMF["DeepMergeFilterValuesURI"] extends keyof DeepMergeFunctionURItoKind + ? PMF["DeepMergeFilterValuesURI"] + : DeepMergeFilterValuesDefaultURI; }>; diff --git a/dist/deno/types/merging.ts b/dist/deno/types/merging.ts index 9ccda959..a47a574a 100644 --- a/dist/deno/types/merging.ts +++ b/dist/deno/types/merging.ts @@ -1,5 +1,6 @@ import { type DeepMergeArraysDefaultHKT, + type DeepMergeFilterValuesDefaultHKT, type DeepMergeMapsDefaultHKT, type DeepMergeRecordsDefaultHKT, type DeepMergeSetsDefaultHKT, @@ -9,75 +10,80 @@ import { type EveryIsMap, type EveryIsRecord, type EveryIsSet, - type Is, type IsNever, type IsTuple, - type Or, } from "./utils.ts"; /** * Mapping of merge function URIs to the merge function type. */ // eslint-disable-next-line ts/consistent-type-definitions -export interface DeepMergeMergeFunctionURItoKind< +export interface DeepMergeFunctionURItoKind< Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs, + Fs extends DeepMergeFunctionsURIs, in out M, > { readonly DeepMergeLeafURI: DeepMergeLeaf; - readonly DeepMergeRecordsDefaultURI: DeepMergeRecordsDefaultHKT; - readonly DeepMergeArraysDefaultURI: DeepMergeArraysDefaultHKT; + readonly DeepMergeRecordsDefaultURI: DeepMergeRecordsDefaultHKT; + readonly DeepMergeArraysDefaultURI: DeepMergeArraysDefaultHKT; readonly DeepMergeSetsDefaultURI: DeepMergeSetsDefaultHKT; readonly DeepMergeMapsDefaultURI: DeepMergeMapsDefaultHKT; + readonly DeepMergeFilterValuesDefaultURI: DeepMergeFilterValuesDefaultHKT; + readonly DeepMergeNoFilteringURI: Ts; } /** * Get the type of the given merge function via its URI. */ -type DeepMergeMergeFunctionKind< - URI extends DeepMergeMergeFunctionURIs, +type DeepMergeFunctionKind< + URI extends DeepMergeFunctionURIs, Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs, + Fs extends DeepMergeFunctionsURIs, M, -> = DeepMergeMergeFunctionURItoKind[URI]; +> = DeepMergeFunctionURItoKind[URI]; /** * A union of all valid merge function URIs. */ -type DeepMergeMergeFunctionURIs = keyof DeepMergeMergeFunctionURItoKind< +type DeepMergeFunctionURIs = keyof DeepMergeFunctionURItoKind< ReadonlyArray, - DeepMergeMergeFunctionsURIs, + DeepMergeFunctionsURIs, unknown >; /** * The merge functions to use when deep merging. */ -export type DeepMergeMergeFunctionsURIs = Readonly<{ +export type DeepMergeFunctionsURIs = Readonly<{ /** * The merge function to merge records with. */ - DeepMergeRecordsURI: DeepMergeMergeFunctionURIs; + DeepMergeRecordsURI: DeepMergeFunctionURIs; /** * The merge function to merge arrays with. */ - DeepMergeArraysURI: DeepMergeMergeFunctionURIs; + DeepMergeArraysURI: DeepMergeFunctionURIs; /** * The merge function to merge sets with. */ - DeepMergeSetsURI: DeepMergeMergeFunctionURIs; + DeepMergeSetsURI: DeepMergeFunctionURIs; /** * The merge function to merge maps with. */ - DeepMergeMapsURI: DeepMergeMergeFunctionURIs; + DeepMergeMapsURI: DeepMergeFunctionURIs; /** * The merge function to merge other things with. */ - DeepMergeOthersURI: DeepMergeMergeFunctionURIs; + DeepMergeOthersURI: DeepMergeFunctionURIs; + + /** + * The function to filter values. + */ + DeepMergeFilterValuesURI: DeepMergeFunctionURIs; }>; /** @@ -85,75 +91,98 @@ export type DeepMergeMergeFunctionsURIs = Readonly<{ */ export type DeepMergeHKT< Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs, + Fs extends DeepMergeFunctionsURIs, M, > = IsTuple extends true ? Ts extends readonly [] ? undefined - : Ts extends readonly [infer T1] - ? T1 - : EveryIsArray extends true - ? DeepMergeArraysHKT - : EveryIsMap extends true - ? DeepMergeMapsHKT - : EveryIsSet extends true - ? DeepMergeSetsHKT - : EveryIsRecord extends true - ? DeepMergeRecordsHKT - : DeepMergeOthersHKT + : DeepMergeHKTHelper, Fs, M> : unknown; +type DeepMergeHKTHelper = + Ts extends ReadonlyArray + ? IsTuple extends true + ? Ts extends readonly [] + ? unknown + : Ts extends readonly [infer T1] + ? T1 + : EveryIsArray extends true + ? DeepMergeArraysHKT + : EveryIsMap extends true + ? DeepMergeMapsHKT + : EveryIsSet extends true + ? DeepMergeSetsHKT + : EveryIsRecord extends true + ? DeepMergeRecordsHKT + : DeepMergeOthersHKT + : unknown + : never; + /** * Deep merge records. */ type DeepMergeRecordsHKT< Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs, + Fs extends DeepMergeFunctionsURIs, M, -> = DeepMergeMergeFunctionKind; +> = DeepMergeFunctionKind; /** * Deep merge arrays. */ type DeepMergeArraysHKT< Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs, + Fs extends DeepMergeFunctionsURIs, M, -> = DeepMergeMergeFunctionKind; +> = DeepMergeFunctionKind; /** * Deep merge sets. */ type DeepMergeSetsHKT< Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs, + Fs extends DeepMergeFunctionsURIs, M, -> = DeepMergeMergeFunctionKind; +> = DeepMergeFunctionKind; /** * Deep merge maps. */ type DeepMergeMapsHKT< Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs, + Fs extends DeepMergeFunctionsURIs, M, -> = DeepMergeMergeFunctionKind; +> = DeepMergeFunctionKind; /** * Deep merge other things. */ type DeepMergeOthersHKT< Ts extends ReadonlyArray, - MF extends DeepMergeMergeFunctionsURIs, + Fs extends DeepMergeFunctionsURIs, + M, +> = DeepMergeFunctionKind; + +/** + * Filter values. + */ +type FilterValuesHKT< + Ts extends ReadonlyArray, + Fs extends DeepMergeFunctionsURIs, M, -> = DeepMergeMergeFunctionKind; +> = DeepMergeFunctionKind; /** * The merge function that returns a leaf. */ export type DeepMergeLeafURI = "DeepMergeLeafURI"; +/** + * Don't filter values. + */ +export type DeepMergeNoFilteringURI = "DeepMergeNoFilteringURI"; + /** * Get the leaf type from many types that can't be merged. */ @@ -163,7 +192,7 @@ export type DeepMergeLeaf> = : Ts extends readonly [infer T] ? T : Ts extends readonly [...infer Rest, infer Tail] - ? Or, Is> extends true + ? IsNever extends true ? Rest extends ReadonlyArray ? DeepMergeLeaf : never diff --git a/dist/deno/types/options.ts b/dist/deno/types/options.ts index 15ecf706..c8b1b0c2 100644 --- a/dist/deno/types/options.ts +++ b/dist/deno/types/options.ts @@ -31,13 +31,14 @@ type DeepMergeOptionsFull< in out M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, > = Readonly<{ - mergeRecords: DeepMergeMergeFunctions["mergeRecords"] | false; - mergeArrays: DeepMergeMergeFunctions["mergeArrays"] | false; - mergeMaps: DeepMergeMergeFunctions["mergeMaps"] | false; - mergeSets: DeepMergeMergeFunctions["mergeSets"] | false; - mergeOthers: DeepMergeMergeFunctions["mergeOthers"]; + mergeRecords: DeepMergeFunctions["mergeRecords"] | false; + mergeArrays: DeepMergeFunctions["mergeArrays"] | false; + mergeMaps: DeepMergeFunctions["mergeMaps"] | false; + mergeSets: DeepMergeFunctions["mergeSets"] | false; + mergeOthers: DeepMergeFunctions["mergeOthers"]; metaDataUpdater: MetaDataUpdater; enableImplicitDefaultMerging: boolean; + filterValues: DeepMergeUtilityFunctions["filterValues"] | false; }>; /** @@ -47,12 +48,13 @@ type DeepMergeIntoOptionsFull< in out M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, > = Readonly<{ - mergeRecords: DeepMergeMergeIntoFunctions["mergeRecords"] | false; - mergeArrays: DeepMergeMergeIntoFunctions["mergeArrays"] | false; - mergeMaps: DeepMergeMergeIntoFunctions["mergeMaps"] | false; - mergeSets: DeepMergeMergeIntoFunctions["mergeSets"] | false; - mergeOthers: DeepMergeMergeIntoFunctions["mergeOthers"]; + mergeRecords: DeepMergeIntoFunctions["mergeRecords"] | false; + mergeArrays: DeepMergeIntoFunctions["mergeArrays"] | false; + mergeMaps: DeepMergeIntoFunctions["mergeMaps"] | false; + mergeSets: DeepMergeIntoFunctions["mergeSets"] | false; + mergeOthers: DeepMergeIntoFunctions["mergeOthers"]; metaDataUpdater: MetaDataUpdater; + filterValues: DeepMergeUtilityFunctions["filterValues"] | false; }>; /** @@ -62,16 +64,26 @@ export type Reference = { value: T; }; +/** + * All the utility functions that can be overridden. + */ +type DeepMergeUtilityFunctions = Readonly<{ + filterValues: >( + values: Ts, + meta: M | undefined, + ) => unknown[]; +}>; + /** * All the merge functions that deepmerge uses. */ -type DeepMergeMergeFunctions< +type DeepMergeFunctions< in M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, > = Readonly<{ mergeRecords: < Ts extends ReadonlyArray>>, - U extends DeepMergeMergeFunctionUtils, + U extends DeepMergeUtils, >( values: Ts, utils: U, @@ -80,7 +92,7 @@ type DeepMergeMergeFunctions< mergeArrays: < Ts extends ReadonlyArray>, - U extends DeepMergeMergeFunctionUtils, + U extends DeepMergeUtils, >( values: Ts, utils: U, @@ -89,7 +101,7 @@ type DeepMergeMergeFunctions< mergeMaps: < Ts extends ReadonlyArray>>, - U extends DeepMergeMergeFunctionUtils, + U extends DeepMergeUtils, >( values: Ts, utils: U, @@ -98,7 +110,7 @@ type DeepMergeMergeFunctions< mergeSets: < Ts extends ReadonlyArray>>, - U extends DeepMergeMergeFunctionUtils, + U extends DeepMergeUtils, >( values: Ts, utils: U, @@ -107,7 +119,7 @@ type DeepMergeMergeFunctions< mergeOthers: < Ts extends ReadonlyArray, - U extends DeepMergeMergeFunctionUtils, + U extends DeepMergeUtils, >( values: Ts, utils: U, @@ -116,78 +128,79 @@ type DeepMergeMergeFunctions< }>; // eslint-disable-next-line ts/no-invalid-void-type -type DeepMergeMergeIntoFunctionsReturnType = void | symbol; +type DeepMergeIntoFunctionsReturnType = void | symbol; /** * All the merge functions that deepmerge uses. */ -type DeepMergeMergeIntoFunctions< +type DeepMergeIntoFunctions< in M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, > = Readonly<{ mergeRecords: < Ts extends ReadonlyArray>>, - U extends DeepMergeMergeIntoFunctionUtils, + U extends DeepMergeIntoFunctionUtils, >( m_target: Reference>, values: Ts, utils: U, meta: M | undefined, - ) => DeepMergeMergeIntoFunctionsReturnType; + ) => DeepMergeIntoFunctionsReturnType; mergeArrays: < Ts extends ReadonlyArray>, - U extends DeepMergeMergeIntoFunctionUtils, + U extends DeepMergeIntoFunctionUtils, >( m_target: Reference, values: Ts, utils: U, meta: M | undefined, - ) => DeepMergeMergeIntoFunctionsReturnType; + ) => DeepMergeIntoFunctionsReturnType; mergeMaps: < Ts extends ReadonlyArray>>, - U extends DeepMergeMergeIntoFunctionUtils, + U extends DeepMergeIntoFunctionUtils, >( m_target: Reference>, values: Ts, utils: U, meta: M | undefined, - ) => DeepMergeMergeIntoFunctionsReturnType; + ) => DeepMergeIntoFunctionsReturnType; mergeSets: < Ts extends ReadonlyArray>>, - U extends DeepMergeMergeIntoFunctionUtils, + U extends DeepMergeIntoFunctionUtils, >( m_target: Reference>, values: Ts, utils: U, meta: M | undefined, - ) => DeepMergeMergeIntoFunctionsReturnType; + ) => DeepMergeIntoFunctionsReturnType; mergeOthers: < Ts extends ReadonlyArray, - U extends DeepMergeMergeIntoFunctionUtils, + U extends DeepMergeIntoFunctionUtils, >( m_target: Reference, values: Ts, utils: U, meta: M | undefined, - ) => DeepMergeMergeIntoFunctionsReturnType; + ) => DeepMergeIntoFunctionsReturnType; }>; /** * The utils provided to the merge functions. */ -export type DeepMergeMergeFunctionUtils< +export type DeepMergeUtils< in out M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, > = Readonly<{ - mergeFunctions: DeepMergeMergeFunctions; + mergeFunctions: DeepMergeFunctions; defaultMergeFunctions: MergeFunctions; metaDataUpdater: MetaDataUpdater; deepmerge: >(...values: Ts) => unknown; useImplicitDefaultMerging: boolean; + filterValues: DeepMergeUtilityFunctions["filterValues"] | undefined; actions: Readonly<{ defaultMerge: symbol; skip: symbol; @@ -197,17 +210,18 @@ export type DeepMergeMergeFunctionUtils< /** * The utils provided to the merge functions. */ -export type DeepMergeMergeIntoFunctionUtils< +export type DeepMergeIntoFunctionUtils< in out M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, > = Readonly<{ - mergeFunctions: DeepMergeMergeIntoFunctions; + mergeFunctions: DeepMergeIntoFunctions; defaultMergeFunctions: MergeIntoFunctions; metaDataUpdater: MetaDataUpdater; deepmergeInto: >( target: Target, ...values: Ts ) => void; + filterValues: DeepMergeUtilityFunctions["filterValues"] | undefined; actions: Readonly<{ defaultMerge: symbol; }>; diff --git a/dist/deno/types/utils.ts b/dist/deno/types/utils.ts index 83a049da..8ec7a1d0 100644 --- a/dist/deno/types/utils.ts +++ b/dist/deno/types/utils.ts @@ -226,25 +226,35 @@ type UnionMapValuesHelper< : Acc; /** - * Filter out nevers from a tuple. + * Filter out U from a tuple. */ -export type FilterOutNever = - T extends ReadonlyArray ? FilterOutNeverHelper : never; +export type FilterOut, U> = FilterOutHelper< + T, + U, + [] +>; /** - * Tail-recursive helper type for FilterOutNever. + * Tail-recursive helper type for FilterOut. */ -type FilterOutNeverHelper< +type FilterOutHelper< T extends ReadonlyArray, + U, Acc extends ReadonlyArray, > = T extends readonly [] ? Acc : T extends readonly [infer Head, ...infer Rest] - ? IsNever extends true - ? FilterOutNeverHelper - : FilterOutNeverHelper + ? Is extends true + ? FilterOutHelper + : FilterOutHelper : T; +/** + * Filter out nevers from a tuple. + */ +export type FilterOutNever = + T extends ReadonlyArray ? FilterOut : never; + /** * Is the type a tuple? */ diff --git a/dist/node/index.cjs b/dist/node/index.cjs index 76a9b1c8..50955e04 100644 --- a/dist/node/index.cjs +++ b/dist/node/index.cjs @@ -16,10 +16,20 @@ const actionsInto = { /** * The default function to update meta data. + * + * It doesn't update the meta data. */ function defaultMetaDataUpdater(previousMeta, metaMeta) { return metaMeta; } +/** + * The default function to filter values. + * + * It filters out undefined values. + */ +function defaultFilterValues(values, meta) { + return values.filter((value) => value !== undefined); +} /** * The different types of objects deepmerge-ts support. @@ -203,12 +213,7 @@ function mergeMaps$2(values) { * Get the last non-undefined value in the given array. */ function mergeOthers$2(values) { - for (let i = values.length - 1; i >= 0; i--) { - if (values[i] !== undefined) { - return values[i]; - } - } - return undefined; + return values.at(-1); } var defaultMergeFunctions = /*#__PURE__*/Object.freeze({ @@ -258,6 +263,9 @@ function getUtils(options, customizedDeepmerge) { defaultMetaDataUpdater), deepmerge: customizedDeepmerge, useImplicitDefaultMerging: options.enableImplicitDefaultMerging ?? false, + filterValues: options.filterValues === false + ? undefined + : options.filterValues ?? defaultFilterValues, actions, }; } @@ -267,36 +275,37 @@ function getUtils(options, customizedDeepmerge) { * @param values - The values. */ function mergeUnknowns(values, utils, meta) { - if (values.length === 0) { + const filteredValues = utils.filterValues?.(values, meta) ?? values; + if (filteredValues.length === 0) { return undefined; } - if (values.length === 1) { - return mergeOthers$1(values, utils, meta); + if (filteredValues.length === 1) { + return mergeOthers$1(filteredValues, utils, meta); } - const type = getObjectType(values[0]); + const type = getObjectType(filteredValues[0]); if (type !== 0 /* ObjectType.NOT */ && type !== 5 /* ObjectType.OTHER */) { - for (let m_index = 1; m_index < values.length; m_index++) { - if (getObjectType(values[m_index]) === type) { + for (let m_index = 1; m_index < filteredValues.length; m_index++) { + if (getObjectType(filteredValues[m_index]) === type) { continue; } - return mergeOthers$1(values, utils, meta); + return mergeOthers$1(filteredValues, utils, meta); } } switch (type) { case 1 /* ObjectType.RECORD */: { - return mergeRecords$1(values, utils, meta); + return mergeRecords$1(filteredValues, utils, meta); } case 2 /* ObjectType.ARRAY */: { - return mergeArrays$1(values, utils, meta); + return mergeArrays$1(filteredValues, utils, meta); } case 3 /* ObjectType.SET */: { - return mergeSets$1(values, utils, meta); + return mergeSets$1(filteredValues, utils, meta); } case 4 /* ObjectType.MAP */: { - return mergeMaps$1(values, utils, meta); + return mergeMaps$1(filteredValues, utils, meta); } default: { - return mergeOthers$1(values, utils, meta); + return mergeOthers$1(filteredValues, utils, meta); } } } @@ -450,13 +459,7 @@ function mergeMaps(m_target, values) { * Set the target to the last non-undefined value. */ function mergeOthers(m_target, values) { - for (let i = values.length - 1; i >= 0; i--) { - if (values[i] !== undefined) { - m_target.value = values[i]; - return; - } - } - m_target.value = undefined; + m_target.value = values.at(-1); } var defaultMergeIntoFunctions = /*#__PURE__*/Object.freeze({ @@ -500,6 +503,9 @@ function getIntoUtils(options, customizedDeepmergeInto) { metaDataUpdater: (options.metaDataUpdater ?? defaultMetaDataUpdater), deepmergeInto: customizedDeepmergeInto, + filterValues: options.filterValues === false + ? undefined + : options.filterValues ?? defaultFilterValues, actions: actionsInto, }; } @@ -510,36 +516,37 @@ function getIntoUtils(options, customizedDeepmergeInto) { * @param values - The values. */ function mergeUnknownsInto(m_target, values, utils, meta) { - if (values.length === 0) { + const filteredValues = utils.filterValues?.(values, meta) ?? values; + if (filteredValues.length === 0) { return; } - if (values.length === 1) { - return void mergeOthersInto(m_target, values, utils, meta); + if (filteredValues.length === 1) { + return void mergeOthersInto(m_target, filteredValues, utils, meta); } const type = getObjectType(m_target.value); if (type !== 0 /* ObjectType.NOT */ && type !== 5 /* ObjectType.OTHER */) { - for (let m_index = 1; m_index < values.length; m_index++) { - if (getObjectType(values[m_index]) === type) { + for (let m_index = 1; m_index < filteredValues.length; m_index++) { + if (getObjectType(filteredValues[m_index]) === type) { continue; } - return void mergeOthersInto(m_target, values, utils, meta); + return void mergeOthersInto(m_target, filteredValues, utils, meta); } } switch (type) { case 1 /* ObjectType.RECORD */: { - return void mergeRecordsInto(m_target, values, utils, meta); + return void mergeRecordsInto(m_target, filteredValues, utils, meta); } case 2 /* ObjectType.ARRAY */: { - return void mergeArraysInto(m_target, values, utils, meta); + return void mergeArraysInto(m_target, filteredValues, utils, meta); } case 3 /* ObjectType.SET */: { - return void mergeSetsInto(m_target, values, utils, meta); + return void mergeSetsInto(m_target, filteredValues, utils, meta); } case 4 /* ObjectType.MAP */: { - return void mergeMapsInto(m_target, values, utils, meta); + return void mergeMapsInto(m_target, filteredValues, utils, meta); } default: { - return void mergeOthersInto(m_target, values, utils, meta); + return void mergeOthersInto(m_target, filteredValues, utils, meta); } } } diff --git a/dist/node/index.d.cts b/dist/node/index.d.cts index 9685a256..ce5894d3 100644 --- a/dist/node/index.d.cts +++ b/dist/node/index.d.cts @@ -47,10 +47,6 @@ type IsNever = Is; * And operator for types. */ type And = T1 extends false ? false : T2; -/** - * Or operator for types. - */ -type Or = T1 extends true ? true : T2; /** * Not operator for types. */ @@ -162,21 +158,25 @@ type UnionMapValuesHelper, Acc> = Ts extends r ] ? Head extends Readonly> ? Rest extends readonly [ ] ? Acc | V1 : UnionMapValuesHelper : never : Acc; /** - * Filter out nevers from a tuple. + * Filter out U from a tuple. */ -type FilterOutNever = T extends ReadonlyArray ? FilterOutNeverHelper : never; +type FilterOut, U> = FilterOutHelper; /** - * Tail-recursive helper type for FilterOutNever. + * Tail-recursive helper type for FilterOut. */ -type FilterOutNeverHelper, Acc extends ReadonlyArray> = T extends readonly [ +type FilterOutHelper, U, Acc extends ReadonlyArray> = T extends readonly [ ] ? Acc : T extends readonly [ infer Head, ...infer Rest -] ? IsNever extends true ? FilterOutNeverHelper : FilterOutNeverHelper extends true ? FilterOutHelper : FilterOutHelper : T; +/** + * Filter out nevers from a tuple. + */ +type FilterOutNever = T extends ReadonlyArray ? FilterOut : never; /** * Is the type a tuple? */ @@ -255,77 +255,93 @@ type LastOf = UnionToIntersection T : never> extends () * Mapping of merge function URIs to the merge function type. */ // eslint-disable-next-line ts/consistent-type-definitions -interface DeepMergeMergeFunctionURItoKind, MF extends DeepMergeMergeFunctionsURIs, in out M> { +interface DeepMergeFunctionURItoKind, Fs extends DeepMergeFunctionsURIs, in out M> { readonly DeepMergeLeafURI: DeepMergeLeaf; - readonly DeepMergeRecordsDefaultURI: DeepMergeRecordsDefaultHKT; - readonly DeepMergeArraysDefaultURI: DeepMergeArraysDefaultHKT; + readonly DeepMergeRecordsDefaultURI: DeepMergeRecordsDefaultHKT; + readonly DeepMergeArraysDefaultURI: DeepMergeArraysDefaultHKT; readonly DeepMergeSetsDefaultURI: DeepMergeSetsDefaultHKT; readonly DeepMergeMapsDefaultURI: DeepMergeMapsDefaultHKT; + readonly DeepMergeFilterValuesDefaultURI: DeepMergeFilterValuesDefaultHKT; + readonly DeepMergeNoFilteringURI: Ts; } /** * Get the type of the given merge function via its URI. */ -type DeepMergeMergeFunctionKind, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionURItoKind[URI]; +type DeepMergeFunctionKind, Fs extends DeepMergeFunctionsURIs, M> = DeepMergeFunctionURItoKind[URI]; /** * A union of all valid merge function URIs. */ -type DeepMergeMergeFunctionURIs = keyof DeepMergeMergeFunctionURItoKind, DeepMergeMergeFunctionsURIs, unknown>; +type DeepMergeFunctionURIs = keyof DeepMergeFunctionURItoKind, DeepMergeFunctionsURIs, unknown>; /** * The merge functions to use when deep merging. */ -type DeepMergeMergeFunctionsURIs = Readonly<{ +type DeepMergeFunctionsURIs = Readonly<{ /** * The merge function to merge records with. */ - DeepMergeRecordsURI: DeepMergeMergeFunctionURIs; + DeepMergeRecordsURI: DeepMergeFunctionURIs; /** * The merge function to merge arrays with. */ - DeepMergeArraysURI: DeepMergeMergeFunctionURIs; + DeepMergeArraysURI: DeepMergeFunctionURIs; /** * The merge function to merge sets with. */ - DeepMergeSetsURI: DeepMergeMergeFunctionURIs; + DeepMergeSetsURI: DeepMergeFunctionURIs; /** * The merge function to merge maps with. */ - DeepMergeMapsURI: DeepMergeMergeFunctionURIs; + DeepMergeMapsURI: DeepMergeFunctionURIs; /** * The merge function to merge other things with. */ - DeepMergeOthersURI: DeepMergeMergeFunctionURIs; + DeepMergeOthersURI: DeepMergeFunctionURIs; + /** + * The function to filter values. + */ + DeepMergeFilterValuesURI: DeepMergeFunctionURIs; }>; /** * Deep merge types. */ -type DeepMergeHKT, MF extends DeepMergeMergeFunctionsURIs, M> = IsTuple extends true ? Ts extends readonly [ -] ? undefined : Ts extends readonly [ +type DeepMergeHKT, Fs extends DeepMergeFunctionsURIs, M> = IsTuple extends true ? Ts extends readonly [ +] ? undefined : DeepMergeHKTHelper, Fs, M> : unknown; +type DeepMergeHKTHelper = Ts extends ReadonlyArray ? IsTuple extends true ? Ts extends readonly [ +] ? unknown : Ts extends readonly [ infer T1 -] ? T1 : EveryIsArray extends true ? DeepMergeArraysHKT : EveryIsMap extends true ? DeepMergeMapsHKT : EveryIsSet extends true ? DeepMergeSetsHKT : EveryIsRecord extends true ? DeepMergeRecordsHKT : DeepMergeOthersHKT : unknown; +] ? T1 : EveryIsArray extends true ? DeepMergeArraysHKT : EveryIsMap extends true ? DeepMergeMapsHKT : EveryIsSet extends true ? DeepMergeSetsHKT : EveryIsRecord extends true ? DeepMergeRecordsHKT : DeepMergeOthersHKT : unknown : never; /** * Deep merge records. */ -type DeepMergeRecordsHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionKind; +type DeepMergeRecordsHKT, Fs extends DeepMergeFunctionsURIs, M> = DeepMergeFunctionKind; /** * Deep merge arrays. */ -type DeepMergeArraysHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionKind; +type DeepMergeArraysHKT, Fs extends DeepMergeFunctionsURIs, M> = DeepMergeFunctionKind; /** * Deep merge sets. */ -type DeepMergeSetsHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionKind; +type DeepMergeSetsHKT, Fs extends DeepMergeFunctionsURIs, M> = DeepMergeFunctionKind; /** * Deep merge maps. */ -type DeepMergeMapsHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionKind; +type DeepMergeMapsHKT, Fs extends DeepMergeFunctionsURIs, M> = DeepMergeFunctionKind; /** * Deep merge other things. */ -type DeepMergeOthersHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionKind; +type DeepMergeOthersHKT, Fs extends DeepMergeFunctionsURIs, M> = DeepMergeFunctionKind; +/** + * Filter values. + */ +type FilterValuesHKT, Fs extends DeepMergeFunctionsURIs, M> = DeepMergeFunctionKind; /** * The merge function that returns a leaf. */ type DeepMergeLeafURI = "DeepMergeLeafURI"; +/** + * Don't filter values. + */ +type DeepMergeNoFilteringURI = "DeepMergeNoFilteringURI"; /** * Get the leaf type from many types that can't be merged. */ @@ -335,7 +351,7 @@ type DeepMergeLeaf> = Ts extends readonly [ ] ? T : Ts extends readonly [ ...infer Rest, infer Tail -] ? Or, Is> extends true ? Rest extends ReadonlyArray ? DeepMergeLeaf : never : Tail : never; +] ? IsNever extends true ? Rest extends ReadonlyArray ? DeepMergeLeaf : never : Tail : never; /** * The meta data deepmerge is able to provide. */ @@ -359,15 +375,20 @@ type DeepMergeSetsDefaultURI = "DeepMergeSetsDefaultURI"; * The default merge function to merge maps with. */ type DeepMergeMapsDefaultURI = "DeepMergeMapsDefaultURI"; +/** + * The default filter values function. + */ +type DeepMergeFilterValuesDefaultURI = "DeepMergeFilterValuesDefaultURI"; /** * The default merge functions to use when deep merging. */ -type DeepMergeMergeFunctionsDefaultURIs = Readonly<{ +type DeepMergeFunctionsDefaultURIs = Readonly<{ DeepMergeRecordsURI: DeepMergeRecordsDefaultURI; DeepMergeArraysURI: DeepMergeArraysDefaultURI; DeepMergeSetsURI: DeepMergeSetsDefaultURI; DeepMergeMapsURI: DeepMergeMapsDefaultURI; DeepMergeOthersURI: DeepMergeLeafURI; + DeepMergeFilterValuesURI: DeepMergeFilterValuesDefaultURI; }>; type RecordEntries> = TuplifyUnion<{ [K in keyof T]: [ @@ -394,11 +415,11 @@ type RecordToRecordMeta> = object extends /** * Deep merge records. */ -type DeepMergeRecordsDefaultHKT, MF extends DeepMergeMergeFunctionsURIs, M> = Ts extends ReadonlyArray> ? SimplifyObject, MF, M>> : never; +type DeepMergeRecordsDefaultHKT, Fs extends DeepMergeFunctionsURIs, M> = Ts extends ReadonlyArray> ? SimplifyObject, Fs, M>> : never; /** * Deep merge record props. */ -type DeepMergeRecordMetaDefaultHKTProps = RecordMetas extends ReadonlyArray ? CreateRecordFromMeta, MF, M> : never; +type DeepMergeRecordMetaDefaultHKTProps = RecordMetas extends ReadonlyArray ? CreateRecordFromMeta, Fs, M> : never; type MergeRecordMeta> = GroupValuesByKey>; }>>>; @@ -412,17 +433,17 @@ type GroupValuesByKey = Ts extends readonly [ } ? Values[J] : never; }>>; } : never; -type CreateRecordFromMeta = Ts extends ReadonlyArray ? TupleToIntersection<{ +type CreateRecordFromMeta = Ts extends ReadonlyArray ? TupleToIntersection<{ [I in keyof Ts]: Ts[I] extends { key: infer Key extends PropertyKey; values: infer Values extends ReadonlyArray; optional: infer O extends boolean; - } ? CreateRecordForKeyFromMeta : never; + } ? CreateRecordForKeyFromMeta : never; }> : never; -type CreateRecordForKeyFromMeta, Optional extends boolean, MF extends DeepMergeMergeFunctionsURIs, M> = Optional extends true ? { - [k in Key]+?: DeepMergeHKT; +type CreateRecordForKeyFromMeta, Optional extends boolean, Fs extends DeepMergeFunctionsURIs, M> = Optional extends true ? { + [k in Key]+?: DeepMergeHKT; } : { - [k in Key]-?: DeepMergeHKT; + [k in Key]-?: DeepMergeHKT; }; /** * Get the possible types of a property. @@ -513,18 +534,18 @@ type DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeArraysDefaultHKTHelper, Fs extends DeepMergeFunctionsURIs, M> = DeepMergeArraysDefaultHKTHelper; /** * Tail-recursive helper type for DeepMergeArraysDefaultHKT. */ -type DeepMergeArraysDefaultHKTHelper, MF extends DeepMergeMergeFunctionsURIs, M, Acc extends ReadonlyArray> = Ts extends readonly [ +type DeepMergeArraysDefaultHKTHelper, Fs extends DeepMergeFunctionsURIs, M, Acc extends ReadonlyArray> = Ts extends readonly [ infer Head extends ReadonlyArray, ...infer Rest ] ? Rest extends readonly [ ReadonlyArray, ...ReadonlyArray> -] ? DeepMergeArraysDefaultHKTHelper : [ @@ -539,20 +560,26 @@ type DeepMergeSetsDefaultHKT> = Set> = Map, UnionMapValues>; +/** + * Filter out undefined values. + */ +type DeepMergeFilterValuesDefaultHKT> = FilterOut; /** * Get the merge functions with defaults apply from the given subset. */ -type GetDeepMergeMergeFunctionsURIs> = Readonly<{ +type GetDeepMergeFunctionsURIs> = Readonly<{ + // prettier-ignore + DeepMergeRecordsURI: PMF["DeepMergeRecordsURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeRecordsURI"] : DeepMergeRecordsDefaultURI; // prettier-ignore - DeepMergeRecordsURI: PMF["DeepMergeRecordsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeRecordsURI"] : DeepMergeRecordsDefaultURI; + DeepMergeArraysURI: PMF["DeepMergeArraysURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeArraysURI"] : DeepMergeArraysDefaultURI; // prettier-ignore - DeepMergeArraysURI: PMF["DeepMergeArraysURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeArraysURI"] : DeepMergeArraysDefaultURI; + DeepMergeSetsURI: PMF["DeepMergeSetsURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeSetsURI"] : DeepMergeSetsDefaultURI; // prettier-ignore - DeepMergeSetsURI: PMF["DeepMergeSetsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeSetsURI"] : DeepMergeSetsDefaultURI; + DeepMergeMapsURI: PMF["DeepMergeMapsURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeMapsURI"] : DeepMergeMapsDefaultURI; // prettier-ignore - DeepMergeMapsURI: PMF["DeepMergeMapsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeMapsURI"] : DeepMergeMapsDefaultURI; + DeepMergeOthersURI: PMF["DeepMergeOthersURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeOthersURI"] : DeepMergeLeafURI; // prettier-ignore - DeepMergeOthersURI: PMF["DeepMergeOthersURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeOthersURI"] : DeepMergeLeafURI; + DeepMergeFilterValuesURI: PMF["DeepMergeFilterValuesURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeFilterValuesURI"] : DeepMergeFilterValuesDefaultURI; }>; /** * The default merge functions. @@ -570,7 +597,7 @@ type MergeFunctions = { * @param m_target - The result will be mutated into this record * @param values - The records (including the target's value if there is one). */ -declare function mergeRecords>, U extends DeepMergeMergeIntoFunctionUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined): void; +declare function mergeRecords>, U extends DeepMergeIntoFunctionUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined): void; /** * The default strategy to merge arrays into a target array. * @@ -620,24 +647,26 @@ type MetaDataUpdater = Readonly<{ - mergeRecords: DeepMergeMergeFunctions["mergeRecords"] | false; - mergeArrays: DeepMergeMergeFunctions["mergeArrays"] | false; - mergeMaps: DeepMergeMergeFunctions["mergeMaps"] | false; - mergeSets: DeepMergeMergeFunctions["mergeSets"] | false; - mergeOthers: DeepMergeMergeFunctions["mergeOthers"]; + mergeRecords: DeepMergeFunctions["mergeRecords"] | false; + mergeArrays: DeepMergeFunctions["mergeArrays"] | false; + mergeMaps: DeepMergeFunctions["mergeMaps"] | false; + mergeSets: DeepMergeFunctions["mergeSets"] | false; + mergeOthers: DeepMergeFunctions["mergeOthers"]; metaDataUpdater: MetaDataUpdater; enableImplicitDefaultMerging: boolean; + filterValues: DeepMergeUtilityFunctions["filterValues"] | false; }>; /** * All the options the user can pass to customize deepmergeInto. */ type DeepMergeIntoOptionsFull = Readonly<{ - mergeRecords: DeepMergeMergeIntoFunctions["mergeRecords"] | false; - mergeArrays: DeepMergeMergeIntoFunctions["mergeArrays"] | false; - mergeMaps: DeepMergeMergeIntoFunctions["mergeMaps"] | false; - mergeSets: DeepMergeMergeIntoFunctions["mergeSets"] | false; - mergeOthers: DeepMergeMergeIntoFunctions["mergeOthers"]; + mergeRecords: DeepMergeIntoFunctions["mergeRecords"] | false; + mergeArrays: DeepMergeIntoFunctions["mergeArrays"] | false; + mergeMaps: DeepMergeIntoFunctions["mergeMaps"] | false; + mergeSets: DeepMergeIntoFunctions["mergeSets"] | false; + mergeOthers: DeepMergeIntoFunctions["mergeOthers"]; metaDataUpdater: MetaDataUpdater; + filterValues: DeepMergeUtilityFunctions["filterValues"] | false; }>; /** * An object that has a reference to a value. @@ -645,37 +674,44 @@ type DeepMergeIntoOptionsFull = { value: T; }; +/** + * All the utility functions that can be overridden. + */ +type DeepMergeUtilityFunctions = Readonly<{ + filterValues: >(values: Ts, meta: M | undefined) => unknown[]; +}>; /** * All the merge functions that deepmerge uses. */ -type DeepMergeMergeFunctions = Readonly<{ - mergeRecords: >>, U extends DeepMergeMergeFunctionUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; - mergeArrays: >, U extends DeepMergeMergeFunctionUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; - mergeMaps: >>, U extends DeepMergeMergeFunctionUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; - mergeSets: >>, U extends DeepMergeMergeFunctionUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; - mergeOthers: , U extends DeepMergeMergeFunctionUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; +type DeepMergeFunctions = Readonly<{ + mergeRecords: >>, U extends DeepMergeUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; + mergeArrays: >, U extends DeepMergeUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; + mergeMaps: >>, U extends DeepMergeUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; + mergeSets: >>, U extends DeepMergeUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; + mergeOthers: , U extends DeepMergeUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; }>; // eslint-disable-next-line ts/no-invalid-void-type -type DeepMergeMergeIntoFunctionsReturnType = void | symbol; +type DeepMergeIntoFunctionsReturnType = void | symbol; /** * All the merge functions that deepmerge uses. */ -type DeepMergeMergeIntoFunctions = Readonly<{ - mergeRecords: >>, U extends DeepMergeMergeIntoFunctionUtils>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined) => DeepMergeMergeIntoFunctionsReturnType; - mergeArrays: >, U extends DeepMergeMergeIntoFunctionUtils>(m_target: Reference, values: Ts, utils: U, meta: M | undefined) => DeepMergeMergeIntoFunctionsReturnType; - mergeMaps: >>, U extends DeepMergeMergeIntoFunctionUtils>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined) => DeepMergeMergeIntoFunctionsReturnType; - mergeSets: >>, U extends DeepMergeMergeIntoFunctionUtils>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined) => DeepMergeMergeIntoFunctionsReturnType; - mergeOthers: , U extends DeepMergeMergeIntoFunctionUtils>(m_target: Reference, values: Ts, utils: U, meta: M | undefined) => DeepMergeMergeIntoFunctionsReturnType; +type DeepMergeIntoFunctions = Readonly<{ + mergeRecords: >>, U extends DeepMergeIntoFunctionUtils>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined) => DeepMergeIntoFunctionsReturnType; + mergeArrays: >, U extends DeepMergeIntoFunctionUtils>(m_target: Reference, values: Ts, utils: U, meta: M | undefined) => DeepMergeIntoFunctionsReturnType; + mergeMaps: >>, U extends DeepMergeIntoFunctionUtils>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined) => DeepMergeIntoFunctionsReturnType; + mergeSets: >>, U extends DeepMergeIntoFunctionUtils>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined) => DeepMergeIntoFunctionsReturnType; + mergeOthers: , U extends DeepMergeIntoFunctionUtils>(m_target: Reference, values: Ts, utils: U, meta: M | undefined) => DeepMergeIntoFunctionsReturnType; }>; /** * The utils provided to the merge functions. */ -type DeepMergeMergeFunctionUtils = Readonly<{ - mergeFunctions: DeepMergeMergeFunctions; +type DeepMergeUtils = Readonly<{ + mergeFunctions: DeepMergeFunctions; defaultMergeFunctions: MergeFunctions$0; metaDataUpdater: MetaDataUpdater; deepmerge: >(...values: Ts) => unknown; useImplicitDefaultMerging: boolean; + filterValues: DeepMergeUtilityFunctions["filterValues"] | undefined; actions: Readonly<{ defaultMerge: symbol; skip: symbol; @@ -684,11 +720,12 @@ type DeepMergeMergeFunctionUtils = Readonly<{ - mergeFunctions: DeepMergeMergeIntoFunctions; +type DeepMergeIntoFunctionUtils = Readonly<{ + mergeFunctions: DeepMergeIntoFunctions; defaultMergeFunctions: MergeIntoFunctions; metaDataUpdater: MetaDataUpdater; deepmergeInto: >(target: Target, ...values: Ts) => void; + filterValues: DeepMergeUtilityFunctions["filterValues"] | undefined; actions: Readonly<{ defaultMerge: symbol; }>; @@ -700,20 +737,20 @@ type DeepMergeMergeIntoFunctionUtils>>(...objects: readonly [ ...Ts -]): DeepMergeHKT; +]): DeepMergeHKT; /** * Deeply merge two or more objects using the given options. * * @param options - The options on how to customize the merge function. */ -declare function deepmergeCustom = {}>(options: DeepMergeOptions): >(...objects: Ts) => DeepMergeHKT, DeepMergeBuiltInMetaData>; +declare function deepmergeCustom = {}>(options: DeepMergeOptions): >(...objects: Ts) => DeepMergeHKT, DeepMergeBuiltInMetaData>; /** * Deeply merge two or more objects using the given options and meta data. * * @param options - The options on how to customize the merge function. * @param rootMetaData - The meta data passed to the root items' being merged. */ -declare function deepmergeCustom = {}, MetaData = DeepMergeBuiltInMetaData, MetaMetaData extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData>(options: DeepMergeOptions, rootMetaData?: MetaData): >(...objects: Ts) => DeepMergeHKT, MetaData>; +declare function deepmergeCustom = {}, MetaData = DeepMergeBuiltInMetaData, MetaMetaData extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData>(options: DeepMergeOptions, rootMetaData?: MetaData): >(...objects: Ts) => DeepMergeHKT, MetaData>; /** * Deeply merge objects into a target. * @@ -730,7 +767,7 @@ declare function deepmergeInto(target: T, ...objects: Readonly declare function deepmergeInto>(target: Target, ...objects: Ts): asserts target is SimplifyObject>; +], DeepMergeFunctionsDefaultURIs, DeepMergeBuiltInMetaData>>; /** * Deeply merge two or more objects using the given options. * @@ -780,4 +817,4 @@ declare function getKeys(objects: ReadonlyArray): Set; */ declare function objectHasProperty(object: object, property: PropertyKey): boolean; export { deepmerge, deepmergeCustom, deepmergeInto, deepmergeIntoCustom, ObjectType, getKeys, getObjectType, objectHasProperty }; -export type { MergeFunctions as DeepMergeMergeIntoFunctionsDefaults, MergeFunctions$0 as DeepMergeMergeFunctionsDefaults, DeepMergeArraysDefaultHKT, DeepMergeBuiltInMetaData, DeepMergeHKT, DeepMergeLeaf, DeepMergeLeafURI, DeepMergeMapsDefaultHKT, DeepMergeMergeFunctionsDefaultURIs, DeepMergeMergeFunctionsURIs, DeepMergeMergeFunctionURItoKind, DeepMergeMergeFunctionUtils, DeepMergeMergeIntoFunctionUtils, DeepMergeOptions, DeepMergeIntoOptions, DeepMergeRecordsDefaultHKT, DeepMergeSetsDefaultHKT, Reference as DeepMergeValueReference, GetDeepMergeMergeFunctionsURIs }; +export type { MergeFunctions as DeepMergeIntoFunctionsDefaults, MergeFunctions$0 as DeepMergeFunctionsDefaults, DeepMergeArraysDefaultHKT, DeepMergeBuiltInMetaData, DeepMergeHKT, DeepMergeLeaf, DeepMergeLeafURI, DeepMergeNoFilteringURI, DeepMergeMapsDefaultHKT, DeepMergeFunctionsDefaultURIs, DeepMergeFunctionsURIs, DeepMergeFunctionURItoKind, DeepMergeUtils, DeepMergeIntoFunctionUtils, DeepMergeOptions, DeepMergeIntoOptions, DeepMergeRecordsDefaultHKT, DeepMergeSetsDefaultHKT, Reference as DeepMergeValueReference, GetDeepMergeFunctionsURIs, FilterOut }; diff --git a/dist/node/index.d.mts b/dist/node/index.d.mts index 9685a256..ce5894d3 100644 --- a/dist/node/index.d.mts +++ b/dist/node/index.d.mts @@ -47,10 +47,6 @@ type IsNever = Is; * And operator for types. */ type And = T1 extends false ? false : T2; -/** - * Or operator for types. - */ -type Or = T1 extends true ? true : T2; /** * Not operator for types. */ @@ -162,21 +158,25 @@ type UnionMapValuesHelper, Acc> = Ts extends r ] ? Head extends Readonly> ? Rest extends readonly [ ] ? Acc | V1 : UnionMapValuesHelper : never : Acc; /** - * Filter out nevers from a tuple. + * Filter out U from a tuple. */ -type FilterOutNever = T extends ReadonlyArray ? FilterOutNeverHelper : never; +type FilterOut, U> = FilterOutHelper; /** - * Tail-recursive helper type for FilterOutNever. + * Tail-recursive helper type for FilterOut. */ -type FilterOutNeverHelper, Acc extends ReadonlyArray> = T extends readonly [ +type FilterOutHelper, U, Acc extends ReadonlyArray> = T extends readonly [ ] ? Acc : T extends readonly [ infer Head, ...infer Rest -] ? IsNever extends true ? FilterOutNeverHelper : FilterOutNeverHelper extends true ? FilterOutHelper : FilterOutHelper : T; +/** + * Filter out nevers from a tuple. + */ +type FilterOutNever = T extends ReadonlyArray ? FilterOut : never; /** * Is the type a tuple? */ @@ -255,77 +255,93 @@ type LastOf = UnionToIntersection T : never> extends () * Mapping of merge function URIs to the merge function type. */ // eslint-disable-next-line ts/consistent-type-definitions -interface DeepMergeMergeFunctionURItoKind, MF extends DeepMergeMergeFunctionsURIs, in out M> { +interface DeepMergeFunctionURItoKind, Fs extends DeepMergeFunctionsURIs, in out M> { readonly DeepMergeLeafURI: DeepMergeLeaf; - readonly DeepMergeRecordsDefaultURI: DeepMergeRecordsDefaultHKT; - readonly DeepMergeArraysDefaultURI: DeepMergeArraysDefaultHKT; + readonly DeepMergeRecordsDefaultURI: DeepMergeRecordsDefaultHKT; + readonly DeepMergeArraysDefaultURI: DeepMergeArraysDefaultHKT; readonly DeepMergeSetsDefaultURI: DeepMergeSetsDefaultHKT; readonly DeepMergeMapsDefaultURI: DeepMergeMapsDefaultHKT; + readonly DeepMergeFilterValuesDefaultURI: DeepMergeFilterValuesDefaultHKT; + readonly DeepMergeNoFilteringURI: Ts; } /** * Get the type of the given merge function via its URI. */ -type DeepMergeMergeFunctionKind, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionURItoKind[URI]; +type DeepMergeFunctionKind, Fs extends DeepMergeFunctionsURIs, M> = DeepMergeFunctionURItoKind[URI]; /** * A union of all valid merge function URIs. */ -type DeepMergeMergeFunctionURIs = keyof DeepMergeMergeFunctionURItoKind, DeepMergeMergeFunctionsURIs, unknown>; +type DeepMergeFunctionURIs = keyof DeepMergeFunctionURItoKind, DeepMergeFunctionsURIs, unknown>; /** * The merge functions to use when deep merging. */ -type DeepMergeMergeFunctionsURIs = Readonly<{ +type DeepMergeFunctionsURIs = Readonly<{ /** * The merge function to merge records with. */ - DeepMergeRecordsURI: DeepMergeMergeFunctionURIs; + DeepMergeRecordsURI: DeepMergeFunctionURIs; /** * The merge function to merge arrays with. */ - DeepMergeArraysURI: DeepMergeMergeFunctionURIs; + DeepMergeArraysURI: DeepMergeFunctionURIs; /** * The merge function to merge sets with. */ - DeepMergeSetsURI: DeepMergeMergeFunctionURIs; + DeepMergeSetsURI: DeepMergeFunctionURIs; /** * The merge function to merge maps with. */ - DeepMergeMapsURI: DeepMergeMergeFunctionURIs; + DeepMergeMapsURI: DeepMergeFunctionURIs; /** * The merge function to merge other things with. */ - DeepMergeOthersURI: DeepMergeMergeFunctionURIs; + DeepMergeOthersURI: DeepMergeFunctionURIs; + /** + * The function to filter values. + */ + DeepMergeFilterValuesURI: DeepMergeFunctionURIs; }>; /** * Deep merge types. */ -type DeepMergeHKT, MF extends DeepMergeMergeFunctionsURIs, M> = IsTuple extends true ? Ts extends readonly [ -] ? undefined : Ts extends readonly [ +type DeepMergeHKT, Fs extends DeepMergeFunctionsURIs, M> = IsTuple extends true ? Ts extends readonly [ +] ? undefined : DeepMergeHKTHelper, Fs, M> : unknown; +type DeepMergeHKTHelper = Ts extends ReadonlyArray ? IsTuple extends true ? Ts extends readonly [ +] ? unknown : Ts extends readonly [ infer T1 -] ? T1 : EveryIsArray extends true ? DeepMergeArraysHKT : EveryIsMap extends true ? DeepMergeMapsHKT : EveryIsSet extends true ? DeepMergeSetsHKT : EveryIsRecord extends true ? DeepMergeRecordsHKT : DeepMergeOthersHKT : unknown; +] ? T1 : EveryIsArray extends true ? DeepMergeArraysHKT : EveryIsMap extends true ? DeepMergeMapsHKT : EveryIsSet extends true ? DeepMergeSetsHKT : EveryIsRecord extends true ? DeepMergeRecordsHKT : DeepMergeOthersHKT : unknown : never; /** * Deep merge records. */ -type DeepMergeRecordsHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionKind; +type DeepMergeRecordsHKT, Fs extends DeepMergeFunctionsURIs, M> = DeepMergeFunctionKind; /** * Deep merge arrays. */ -type DeepMergeArraysHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionKind; +type DeepMergeArraysHKT, Fs extends DeepMergeFunctionsURIs, M> = DeepMergeFunctionKind; /** * Deep merge sets. */ -type DeepMergeSetsHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionKind; +type DeepMergeSetsHKT, Fs extends DeepMergeFunctionsURIs, M> = DeepMergeFunctionKind; /** * Deep merge maps. */ -type DeepMergeMapsHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionKind; +type DeepMergeMapsHKT, Fs extends DeepMergeFunctionsURIs, M> = DeepMergeFunctionKind; /** * Deep merge other things. */ -type DeepMergeOthersHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionKind; +type DeepMergeOthersHKT, Fs extends DeepMergeFunctionsURIs, M> = DeepMergeFunctionKind; +/** + * Filter values. + */ +type FilterValuesHKT, Fs extends DeepMergeFunctionsURIs, M> = DeepMergeFunctionKind; /** * The merge function that returns a leaf. */ type DeepMergeLeafURI = "DeepMergeLeafURI"; +/** + * Don't filter values. + */ +type DeepMergeNoFilteringURI = "DeepMergeNoFilteringURI"; /** * Get the leaf type from many types that can't be merged. */ @@ -335,7 +351,7 @@ type DeepMergeLeaf> = Ts extends readonly [ ] ? T : Ts extends readonly [ ...infer Rest, infer Tail -] ? Or, Is> extends true ? Rest extends ReadonlyArray ? DeepMergeLeaf : never : Tail : never; +] ? IsNever extends true ? Rest extends ReadonlyArray ? DeepMergeLeaf : never : Tail : never; /** * The meta data deepmerge is able to provide. */ @@ -359,15 +375,20 @@ type DeepMergeSetsDefaultURI = "DeepMergeSetsDefaultURI"; * The default merge function to merge maps with. */ type DeepMergeMapsDefaultURI = "DeepMergeMapsDefaultURI"; +/** + * The default filter values function. + */ +type DeepMergeFilterValuesDefaultURI = "DeepMergeFilterValuesDefaultURI"; /** * The default merge functions to use when deep merging. */ -type DeepMergeMergeFunctionsDefaultURIs = Readonly<{ +type DeepMergeFunctionsDefaultURIs = Readonly<{ DeepMergeRecordsURI: DeepMergeRecordsDefaultURI; DeepMergeArraysURI: DeepMergeArraysDefaultURI; DeepMergeSetsURI: DeepMergeSetsDefaultURI; DeepMergeMapsURI: DeepMergeMapsDefaultURI; DeepMergeOthersURI: DeepMergeLeafURI; + DeepMergeFilterValuesURI: DeepMergeFilterValuesDefaultURI; }>; type RecordEntries> = TuplifyUnion<{ [K in keyof T]: [ @@ -394,11 +415,11 @@ type RecordToRecordMeta> = object extends /** * Deep merge records. */ -type DeepMergeRecordsDefaultHKT, MF extends DeepMergeMergeFunctionsURIs, M> = Ts extends ReadonlyArray> ? SimplifyObject, MF, M>> : never; +type DeepMergeRecordsDefaultHKT, Fs extends DeepMergeFunctionsURIs, M> = Ts extends ReadonlyArray> ? SimplifyObject, Fs, M>> : never; /** * Deep merge record props. */ -type DeepMergeRecordMetaDefaultHKTProps = RecordMetas extends ReadonlyArray ? CreateRecordFromMeta, MF, M> : never; +type DeepMergeRecordMetaDefaultHKTProps = RecordMetas extends ReadonlyArray ? CreateRecordFromMeta, Fs, M> : never; type MergeRecordMeta> = GroupValuesByKey>; }>>>; @@ -412,17 +433,17 @@ type GroupValuesByKey = Ts extends readonly [ } ? Values[J] : never; }>>; } : never; -type CreateRecordFromMeta = Ts extends ReadonlyArray ? TupleToIntersection<{ +type CreateRecordFromMeta = Ts extends ReadonlyArray ? TupleToIntersection<{ [I in keyof Ts]: Ts[I] extends { key: infer Key extends PropertyKey; values: infer Values extends ReadonlyArray; optional: infer O extends boolean; - } ? CreateRecordForKeyFromMeta : never; + } ? CreateRecordForKeyFromMeta : never; }> : never; -type CreateRecordForKeyFromMeta, Optional extends boolean, MF extends DeepMergeMergeFunctionsURIs, M> = Optional extends true ? { - [k in Key]+?: DeepMergeHKT; +type CreateRecordForKeyFromMeta, Optional extends boolean, Fs extends DeepMergeFunctionsURIs, M> = Optional extends true ? { + [k in Key]+?: DeepMergeHKT; } : { - [k in Key]-?: DeepMergeHKT; + [k in Key]-?: DeepMergeHKT; }; /** * Get the possible types of a property. @@ -513,18 +534,18 @@ type DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeArraysDefaultHKTHelper, Fs extends DeepMergeFunctionsURIs, M> = DeepMergeArraysDefaultHKTHelper; /** * Tail-recursive helper type for DeepMergeArraysDefaultHKT. */ -type DeepMergeArraysDefaultHKTHelper, MF extends DeepMergeMergeFunctionsURIs, M, Acc extends ReadonlyArray> = Ts extends readonly [ +type DeepMergeArraysDefaultHKTHelper, Fs extends DeepMergeFunctionsURIs, M, Acc extends ReadonlyArray> = Ts extends readonly [ infer Head extends ReadonlyArray, ...infer Rest ] ? Rest extends readonly [ ReadonlyArray, ...ReadonlyArray> -] ? DeepMergeArraysDefaultHKTHelper : [ @@ -539,20 +560,26 @@ type DeepMergeSetsDefaultHKT> = Set> = Map, UnionMapValues>; +/** + * Filter out undefined values. + */ +type DeepMergeFilterValuesDefaultHKT> = FilterOut; /** * Get the merge functions with defaults apply from the given subset. */ -type GetDeepMergeMergeFunctionsURIs> = Readonly<{ +type GetDeepMergeFunctionsURIs> = Readonly<{ + // prettier-ignore + DeepMergeRecordsURI: PMF["DeepMergeRecordsURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeRecordsURI"] : DeepMergeRecordsDefaultURI; // prettier-ignore - DeepMergeRecordsURI: PMF["DeepMergeRecordsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeRecordsURI"] : DeepMergeRecordsDefaultURI; + DeepMergeArraysURI: PMF["DeepMergeArraysURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeArraysURI"] : DeepMergeArraysDefaultURI; // prettier-ignore - DeepMergeArraysURI: PMF["DeepMergeArraysURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeArraysURI"] : DeepMergeArraysDefaultURI; + DeepMergeSetsURI: PMF["DeepMergeSetsURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeSetsURI"] : DeepMergeSetsDefaultURI; // prettier-ignore - DeepMergeSetsURI: PMF["DeepMergeSetsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeSetsURI"] : DeepMergeSetsDefaultURI; + DeepMergeMapsURI: PMF["DeepMergeMapsURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeMapsURI"] : DeepMergeMapsDefaultURI; // prettier-ignore - DeepMergeMapsURI: PMF["DeepMergeMapsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeMapsURI"] : DeepMergeMapsDefaultURI; + DeepMergeOthersURI: PMF["DeepMergeOthersURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeOthersURI"] : DeepMergeLeafURI; // prettier-ignore - DeepMergeOthersURI: PMF["DeepMergeOthersURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeOthersURI"] : DeepMergeLeafURI; + DeepMergeFilterValuesURI: PMF["DeepMergeFilterValuesURI"] extends keyof DeepMergeFunctionURItoKind ? PMF["DeepMergeFilterValuesURI"] : DeepMergeFilterValuesDefaultURI; }>; /** * The default merge functions. @@ -570,7 +597,7 @@ type MergeFunctions = { * @param m_target - The result will be mutated into this record * @param values - The records (including the target's value if there is one). */ -declare function mergeRecords>, U extends DeepMergeMergeIntoFunctionUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined): void; +declare function mergeRecords>, U extends DeepMergeIntoFunctionUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined): void; /** * The default strategy to merge arrays into a target array. * @@ -620,24 +647,26 @@ type MetaDataUpdater = Readonly<{ - mergeRecords: DeepMergeMergeFunctions["mergeRecords"] | false; - mergeArrays: DeepMergeMergeFunctions["mergeArrays"] | false; - mergeMaps: DeepMergeMergeFunctions["mergeMaps"] | false; - mergeSets: DeepMergeMergeFunctions["mergeSets"] | false; - mergeOthers: DeepMergeMergeFunctions["mergeOthers"]; + mergeRecords: DeepMergeFunctions["mergeRecords"] | false; + mergeArrays: DeepMergeFunctions["mergeArrays"] | false; + mergeMaps: DeepMergeFunctions["mergeMaps"] | false; + mergeSets: DeepMergeFunctions["mergeSets"] | false; + mergeOthers: DeepMergeFunctions["mergeOthers"]; metaDataUpdater: MetaDataUpdater; enableImplicitDefaultMerging: boolean; + filterValues: DeepMergeUtilityFunctions["filterValues"] | false; }>; /** * All the options the user can pass to customize deepmergeInto. */ type DeepMergeIntoOptionsFull = Readonly<{ - mergeRecords: DeepMergeMergeIntoFunctions["mergeRecords"] | false; - mergeArrays: DeepMergeMergeIntoFunctions["mergeArrays"] | false; - mergeMaps: DeepMergeMergeIntoFunctions["mergeMaps"] | false; - mergeSets: DeepMergeMergeIntoFunctions["mergeSets"] | false; - mergeOthers: DeepMergeMergeIntoFunctions["mergeOthers"]; + mergeRecords: DeepMergeIntoFunctions["mergeRecords"] | false; + mergeArrays: DeepMergeIntoFunctions["mergeArrays"] | false; + mergeMaps: DeepMergeIntoFunctions["mergeMaps"] | false; + mergeSets: DeepMergeIntoFunctions["mergeSets"] | false; + mergeOthers: DeepMergeIntoFunctions["mergeOthers"]; metaDataUpdater: MetaDataUpdater; + filterValues: DeepMergeUtilityFunctions["filterValues"] | false; }>; /** * An object that has a reference to a value. @@ -645,37 +674,44 @@ type DeepMergeIntoOptionsFull = { value: T; }; +/** + * All the utility functions that can be overridden. + */ +type DeepMergeUtilityFunctions = Readonly<{ + filterValues: >(values: Ts, meta: M | undefined) => unknown[]; +}>; /** * All the merge functions that deepmerge uses. */ -type DeepMergeMergeFunctions = Readonly<{ - mergeRecords: >>, U extends DeepMergeMergeFunctionUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; - mergeArrays: >, U extends DeepMergeMergeFunctionUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; - mergeMaps: >>, U extends DeepMergeMergeFunctionUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; - mergeSets: >>, U extends DeepMergeMergeFunctionUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; - mergeOthers: , U extends DeepMergeMergeFunctionUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; +type DeepMergeFunctions = Readonly<{ + mergeRecords: >>, U extends DeepMergeUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; + mergeArrays: >, U extends DeepMergeUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; + mergeMaps: >>, U extends DeepMergeUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; + mergeSets: >>, U extends DeepMergeUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; + mergeOthers: , U extends DeepMergeUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; }>; // eslint-disable-next-line ts/no-invalid-void-type -type DeepMergeMergeIntoFunctionsReturnType = void | symbol; +type DeepMergeIntoFunctionsReturnType = void | symbol; /** * All the merge functions that deepmerge uses. */ -type DeepMergeMergeIntoFunctions = Readonly<{ - mergeRecords: >>, U extends DeepMergeMergeIntoFunctionUtils>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined) => DeepMergeMergeIntoFunctionsReturnType; - mergeArrays: >, U extends DeepMergeMergeIntoFunctionUtils>(m_target: Reference, values: Ts, utils: U, meta: M | undefined) => DeepMergeMergeIntoFunctionsReturnType; - mergeMaps: >>, U extends DeepMergeMergeIntoFunctionUtils>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined) => DeepMergeMergeIntoFunctionsReturnType; - mergeSets: >>, U extends DeepMergeMergeIntoFunctionUtils>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined) => DeepMergeMergeIntoFunctionsReturnType; - mergeOthers: , U extends DeepMergeMergeIntoFunctionUtils>(m_target: Reference, values: Ts, utils: U, meta: M | undefined) => DeepMergeMergeIntoFunctionsReturnType; +type DeepMergeIntoFunctions = Readonly<{ + mergeRecords: >>, U extends DeepMergeIntoFunctionUtils>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined) => DeepMergeIntoFunctionsReturnType; + mergeArrays: >, U extends DeepMergeIntoFunctionUtils>(m_target: Reference, values: Ts, utils: U, meta: M | undefined) => DeepMergeIntoFunctionsReturnType; + mergeMaps: >>, U extends DeepMergeIntoFunctionUtils>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined) => DeepMergeIntoFunctionsReturnType; + mergeSets: >>, U extends DeepMergeIntoFunctionUtils>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined) => DeepMergeIntoFunctionsReturnType; + mergeOthers: , U extends DeepMergeIntoFunctionUtils>(m_target: Reference, values: Ts, utils: U, meta: M | undefined) => DeepMergeIntoFunctionsReturnType; }>; /** * The utils provided to the merge functions. */ -type DeepMergeMergeFunctionUtils = Readonly<{ - mergeFunctions: DeepMergeMergeFunctions; +type DeepMergeUtils = Readonly<{ + mergeFunctions: DeepMergeFunctions; defaultMergeFunctions: MergeFunctions$0; metaDataUpdater: MetaDataUpdater; deepmerge: >(...values: Ts) => unknown; useImplicitDefaultMerging: boolean; + filterValues: DeepMergeUtilityFunctions["filterValues"] | undefined; actions: Readonly<{ defaultMerge: symbol; skip: symbol; @@ -684,11 +720,12 @@ type DeepMergeMergeFunctionUtils = Readonly<{ - mergeFunctions: DeepMergeMergeIntoFunctions; +type DeepMergeIntoFunctionUtils = Readonly<{ + mergeFunctions: DeepMergeIntoFunctions; defaultMergeFunctions: MergeIntoFunctions; metaDataUpdater: MetaDataUpdater; deepmergeInto: >(target: Target, ...values: Ts) => void; + filterValues: DeepMergeUtilityFunctions["filterValues"] | undefined; actions: Readonly<{ defaultMerge: symbol; }>; @@ -700,20 +737,20 @@ type DeepMergeMergeIntoFunctionUtils>>(...objects: readonly [ ...Ts -]): DeepMergeHKT; +]): DeepMergeHKT; /** * Deeply merge two or more objects using the given options. * * @param options - The options on how to customize the merge function. */ -declare function deepmergeCustom = {}>(options: DeepMergeOptions): >(...objects: Ts) => DeepMergeHKT, DeepMergeBuiltInMetaData>; +declare function deepmergeCustom = {}>(options: DeepMergeOptions): >(...objects: Ts) => DeepMergeHKT, DeepMergeBuiltInMetaData>; /** * Deeply merge two or more objects using the given options and meta data. * * @param options - The options on how to customize the merge function. * @param rootMetaData - The meta data passed to the root items' being merged. */ -declare function deepmergeCustom = {}, MetaData = DeepMergeBuiltInMetaData, MetaMetaData extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData>(options: DeepMergeOptions, rootMetaData?: MetaData): >(...objects: Ts) => DeepMergeHKT, MetaData>; +declare function deepmergeCustom = {}, MetaData = DeepMergeBuiltInMetaData, MetaMetaData extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData>(options: DeepMergeOptions, rootMetaData?: MetaData): >(...objects: Ts) => DeepMergeHKT, MetaData>; /** * Deeply merge objects into a target. * @@ -730,7 +767,7 @@ declare function deepmergeInto(target: T, ...objects: Readonly declare function deepmergeInto>(target: Target, ...objects: Ts): asserts target is SimplifyObject>; +], DeepMergeFunctionsDefaultURIs, DeepMergeBuiltInMetaData>>; /** * Deeply merge two or more objects using the given options. * @@ -780,4 +817,4 @@ declare function getKeys(objects: ReadonlyArray): Set; */ declare function objectHasProperty(object: object, property: PropertyKey): boolean; export { deepmerge, deepmergeCustom, deepmergeInto, deepmergeIntoCustom, ObjectType, getKeys, getObjectType, objectHasProperty }; -export type { MergeFunctions as DeepMergeMergeIntoFunctionsDefaults, MergeFunctions$0 as DeepMergeMergeFunctionsDefaults, DeepMergeArraysDefaultHKT, DeepMergeBuiltInMetaData, DeepMergeHKT, DeepMergeLeaf, DeepMergeLeafURI, DeepMergeMapsDefaultHKT, DeepMergeMergeFunctionsDefaultURIs, DeepMergeMergeFunctionsURIs, DeepMergeMergeFunctionURItoKind, DeepMergeMergeFunctionUtils, DeepMergeMergeIntoFunctionUtils, DeepMergeOptions, DeepMergeIntoOptions, DeepMergeRecordsDefaultHKT, DeepMergeSetsDefaultHKT, Reference as DeepMergeValueReference, GetDeepMergeMergeFunctionsURIs }; +export type { MergeFunctions as DeepMergeIntoFunctionsDefaults, MergeFunctions$0 as DeepMergeFunctionsDefaults, DeepMergeArraysDefaultHKT, DeepMergeBuiltInMetaData, DeepMergeHKT, DeepMergeLeaf, DeepMergeLeafURI, DeepMergeNoFilteringURI, DeepMergeMapsDefaultHKT, DeepMergeFunctionsDefaultURIs, DeepMergeFunctionsURIs, DeepMergeFunctionURItoKind, DeepMergeUtils, DeepMergeIntoFunctionUtils, DeepMergeOptions, DeepMergeIntoOptions, DeepMergeRecordsDefaultHKT, DeepMergeSetsDefaultHKT, Reference as DeepMergeValueReference, GetDeepMergeFunctionsURIs, FilterOut }; diff --git a/dist/node/index.mjs b/dist/node/index.mjs index f8386ad0..d71554bb 100644 --- a/dist/node/index.mjs +++ b/dist/node/index.mjs @@ -14,10 +14,20 @@ const actionsInto = { /** * The default function to update meta data. + * + * It doesn't update the meta data. */ function defaultMetaDataUpdater(previousMeta, metaMeta) { return metaMeta; } +/** + * The default function to filter values. + * + * It filters out undefined values. + */ +function defaultFilterValues(values, meta) { + return values.filter((value) => value !== undefined); +} /** * The different types of objects deepmerge-ts support. @@ -201,12 +211,7 @@ function mergeMaps$2(values) { * Get the last non-undefined value in the given array. */ function mergeOthers$2(values) { - for (let i = values.length - 1; i >= 0; i--) { - if (values[i] !== undefined) { - return values[i]; - } - } - return undefined; + return values.at(-1); } var defaultMergeFunctions = /*#__PURE__*/Object.freeze({ @@ -256,6 +261,9 @@ function getUtils(options, customizedDeepmerge) { defaultMetaDataUpdater), deepmerge: customizedDeepmerge, useImplicitDefaultMerging: options.enableImplicitDefaultMerging ?? false, + filterValues: options.filterValues === false + ? undefined + : options.filterValues ?? defaultFilterValues, actions, }; } @@ -265,36 +273,37 @@ function getUtils(options, customizedDeepmerge) { * @param values - The values. */ function mergeUnknowns(values, utils, meta) { - if (values.length === 0) { + const filteredValues = utils.filterValues?.(values, meta) ?? values; + if (filteredValues.length === 0) { return undefined; } - if (values.length === 1) { - return mergeOthers$1(values, utils, meta); + if (filteredValues.length === 1) { + return mergeOthers$1(filteredValues, utils, meta); } - const type = getObjectType(values[0]); + const type = getObjectType(filteredValues[0]); if (type !== 0 /* ObjectType.NOT */ && type !== 5 /* ObjectType.OTHER */) { - for (let m_index = 1; m_index < values.length; m_index++) { - if (getObjectType(values[m_index]) === type) { + for (let m_index = 1; m_index < filteredValues.length; m_index++) { + if (getObjectType(filteredValues[m_index]) === type) { continue; } - return mergeOthers$1(values, utils, meta); + return mergeOthers$1(filteredValues, utils, meta); } } switch (type) { case 1 /* ObjectType.RECORD */: { - return mergeRecords$1(values, utils, meta); + return mergeRecords$1(filteredValues, utils, meta); } case 2 /* ObjectType.ARRAY */: { - return mergeArrays$1(values, utils, meta); + return mergeArrays$1(filteredValues, utils, meta); } case 3 /* ObjectType.SET */: { - return mergeSets$1(values, utils, meta); + return mergeSets$1(filteredValues, utils, meta); } case 4 /* ObjectType.MAP */: { - return mergeMaps$1(values, utils, meta); + return mergeMaps$1(filteredValues, utils, meta); } default: { - return mergeOthers$1(values, utils, meta); + return mergeOthers$1(filteredValues, utils, meta); } } } @@ -448,13 +457,7 @@ function mergeMaps(m_target, values) { * Set the target to the last non-undefined value. */ function mergeOthers(m_target, values) { - for (let i = values.length - 1; i >= 0; i--) { - if (values[i] !== undefined) { - m_target.value = values[i]; - return; - } - } - m_target.value = undefined; + m_target.value = values.at(-1); } var defaultMergeIntoFunctions = /*#__PURE__*/Object.freeze({ @@ -498,6 +501,9 @@ function getIntoUtils(options, customizedDeepmergeInto) { metaDataUpdater: (options.metaDataUpdater ?? defaultMetaDataUpdater), deepmergeInto: customizedDeepmergeInto, + filterValues: options.filterValues === false + ? undefined + : options.filterValues ?? defaultFilterValues, actions: actionsInto, }; } @@ -508,36 +514,37 @@ function getIntoUtils(options, customizedDeepmergeInto) { * @param values - The values. */ function mergeUnknownsInto(m_target, values, utils, meta) { - if (values.length === 0) { + const filteredValues = utils.filterValues?.(values, meta) ?? values; + if (filteredValues.length === 0) { return; } - if (values.length === 1) { - return void mergeOthersInto(m_target, values, utils, meta); + if (filteredValues.length === 1) { + return void mergeOthersInto(m_target, filteredValues, utils, meta); } const type = getObjectType(m_target.value); if (type !== 0 /* ObjectType.NOT */ && type !== 5 /* ObjectType.OTHER */) { - for (let m_index = 1; m_index < values.length; m_index++) { - if (getObjectType(values[m_index]) === type) { + for (let m_index = 1; m_index < filteredValues.length; m_index++) { + if (getObjectType(filteredValues[m_index]) === type) { continue; } - return void mergeOthersInto(m_target, values, utils, meta); + return void mergeOthersInto(m_target, filteredValues, utils, meta); } } switch (type) { case 1 /* ObjectType.RECORD */: { - return void mergeRecordsInto(m_target, values, utils, meta); + return void mergeRecordsInto(m_target, filteredValues, utils, meta); } case 2 /* ObjectType.ARRAY */: { - return void mergeArraysInto(m_target, values, utils, meta); + return void mergeArraysInto(m_target, filteredValues, utils, meta); } case 3 /* ObjectType.SET */: { - return void mergeSetsInto(m_target, values, utils, meta); + return void mergeSetsInto(m_target, filteredValues, utils, meta); } case 4 /* ObjectType.MAP */: { - return void mergeMapsInto(m_target, values, utils, meta); + return void mergeMapsInto(m_target, filteredValues, utils, meta); } default: { - return void mergeOthersInto(m_target, values, utils, meta); + return void mergeOthersInto(m_target, filteredValues, utils, meta); } } }