diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bb6009b..aaf7fe26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,40 @@ # Changelog All notable changes to this project will be documented in this file. Dates are displayed in UTC. +# [6.0.0](https://github.com/RebeccaStevens/deepmerge-ts/compare/v5.1.0...v6.0.0) (2024-05-19) + + +### Bug Fixes + +* type when merging optional properties of a record ([fa9ace2](https://github.com/RebeccaStevens/deepmerge-ts/commit/fa9ace2a2b38030d12fa85634966d409b8bb123f)) + + +### Build System + +* remove typing support for typescript<4.7 ([f2f5956](https://github.com/RebeccaStevens/deepmerge-ts/commit/f2f5956d653a672073fc3c0174f9d8d6ca9d4371)) + + +### Features + +* allow restricting what types can be passed in as parameters ([69e9ba3](https://github.com/RebeccaStevens/deepmerge-ts/commit/69e9ba3519319eb02763887f457549340e9a9c76)), closes [#305](https://github.com/RebeccaStevens/deepmerge-ts/issues/305) +* remove deprecated type DeepMergeLeafHKT ([1982e56](https://github.com/RebeccaStevens/deepmerge-ts/commit/1982e56016cbbbfd07f78e8512b56e8294ff83c0)) +* undefined will no longer replace defined values by default ([9c86605](https://github.com/RebeccaStevens/deepmerge-ts/commit/9c866054cbade77118b5cd62b1e8e68033fe2879)) + + +### Performance Improvements + +* remove BlacklistedRecordProps ([19d4944](https://github.com/RebeccaStevens/deepmerge-ts/commit/19d4944fa228d66d5af93f419526ffaf8b5a376b)) + + +### BREAKING CHANGES + +* remove deprecated type DeepMergeLeafHKT +* undefined will no longer replace defined values by default +* The order of the generics of `deepmergeCustom` +and `deepmergeIntoCustom` have changed. If you are passing generics +to these functions you need to update them. +* remove typing support for typescript<4.7 + # [5.1.0](https://github.com/RebeccaStevens/deepmerge-ts/compare/v5.0.0...v5.1.0) (2023-04-04) diff --git a/dist/deno/README.md b/dist/deno/README.md index 1b745a47..c0cd28bf 100644 --- a/dist/deno/README.md +++ b/dist/deno/README.md @@ -22,6 +22,14 @@ Deeply merge 2 or more objects respecting type information. [Any donations would be much appreciated](./DONATIONS.md). 😄 +### Enterprise Users + +`deepmerge-ts` is available as part of the Tidelift Subscription. + +Tidelift is working with the maintainers of `deepmerge-ts` and a growing network of open source maintainers to ensure +your open source software supply chain meets enterprise standards now and into the future. +[Learn more.](https://tidelift.com/subscription/pkg/npm-deepmerge-ts?utm_source=npm-deepmerge-ts&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) + ## Installation ### Node @@ -43,8 +51,8 @@ yarn add deepmerge-ts // import_map.json { "imports": { - "deepmerge-ts": "https://deno.land/x/deepmergets@__version__/dist/deno/index.ts" - } + "deepmerge-ts": "https://deno.land/x/deepmergets@__version__/dist/deno/index.ts", + }, } ``` @@ -112,15 +120,18 @@ console.log(merged); // } ``` -You can try out this example at [codesandbox.io](https://codesandbox.io/s/deepmerge-ts-example-iltxby?file=/src/example.ts). +You can try out this example at +[codesandbox.io](https://codesandbox.io/s/deepmerge-ts-example-iltxby?file=/src/example.ts). ### Merging into a Target -You can use `deepmergeInto` if you want to update a target object with the merge result instead of creating a new object. +You can use `deepmergeInto` if you want to update a target object with the merge result instead of creating a new +object. This function is best used with objects that are all of the same type. -Note: If the target object's type is different to the input objects, we'll assert that the target's type has changed (this is not done automatically with `deepmergeIntoCustom`). +Note: If the target object's type differs from the input objects, we'll assert that the target's type has changed +(this is not done automatically with `deepmergeIntoCustom`). ### Customized the Merging Process @@ -131,7 +142,8 @@ See [deepmerge custom docs](./docs/deepmergeCustom.md) for more details. ## Performance -We use smart merging instead of the classic merging strategy which some alternative libraries use. This vastly improves performance, both in execution time and memory usage. +We use smart merging instead of the classic merging strategy which some alternative libraries use. This vastly improves +performance, both in execution time and memory usage. ### Classic Merge (not what we do) @@ -145,7 +157,8 @@ This strategy has large performance issues when lots of items need to be merged. With our smart merging, we look ahead to see what can be merged and only merge those things. -In addition to performance improvements, this strategy merges multiple inputs at once; allowing for benefits such as taking averages of the inputs. +In addition to performance improvements, this strategy merges multiple inputs at once; allowing for benefits such as +taking averages of the inputs. ![smart merge animation](./assets/smart-merge.gif) diff --git a/dist/deno/deepmerge-into.ts b/dist/deno/deepmerge-into.ts index fcf6a0bb..bfd119cc 100644 --- a/dist/deno/deepmerge-into.ts +++ b/dist/deno/deepmerge-into.ts @@ -3,14 +3,14 @@ import * as defaultMergeIntoFunctions from "./defaults/into.ts"; import { defaultMetaDataUpdater } from "./defaults/meta-data-updater.ts"; import { type DeepMergeBuiltInMetaData, + type DeepMergeHKT, type DeepMergeIntoOptions, + type DeepMergeMergeFunctionsDefaultURIs, type DeepMergeMergeIntoFunctionUtils, type Reference, - type DeepMergeHKT, - type DeepMergeMergeFunctionsDefaultURIs, } from "./types/index.ts"; -import { type FlatternAlias } from "./types/utils.ts"; -import { getObjectType, ObjectType } from "./utils.ts"; +import { type SimplifyObject } from "./types/utils.ts"; +import { ObjectType, getObjectType } from "./utils.ts"; /** * Deeply merge objects into a target. @@ -31,11 +31,11 @@ export function deepmergeInto( */ export function deepmergeInto< Target extends object, - Ts extends ReadonlyArray + Ts extends ReadonlyArray, >( target: Target, ...objects: Ts -): asserts target is FlatternAlias< +): asserts target is SimplifyObject< Target & DeepMergeHKT< [Target, ...Ts], @@ -46,11 +46,11 @@ export function deepmergeInto< export function deepmergeInto< Target extends object, - Ts extends ReadonlyArray + Ts extends ReadonlyArray, >( target: Target, ...objects: Ts -): asserts target is FlatternAlias< +): asserts target is SimplifyObject< Target & DeepMergeHKT< [Target, ...Ts], @@ -66,12 +66,12 @@ export function deepmergeInto< * * @param options - The options on how to customize the merge function. */ -export function deepmergeIntoCustom( +export function deepmergeIntoCustom( options: DeepMergeIntoOptions< DeepMergeBuiltInMetaData, DeepMergeBuiltInMetaData - > -): >( + >, +): >( target: Target, ...objects: Ts ) => void; @@ -83,23 +83,25 @@ export function deepmergeIntoCustom( * @param rootMetaData - The meta data passed to the root items' being merged. */ export function deepmergeIntoCustom< - MetaData, - MetaMetaData extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + BaseTs = unknown, + MetaData = DeepMergeBuiltInMetaData, + MetaMetaData extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( options: DeepMergeIntoOptions, - rootMetaData?: MetaData -): >( + rootMetaData?: MetaData, +): >( target: Target, ...objects: Ts ) => void; export function deepmergeIntoCustom< + BaseTs, MetaData, - MetaMetaData extends DeepMergeBuiltInMetaData + MetaMetaData extends DeepMergeBuiltInMetaData, >( options: DeepMergeIntoOptions, - rootMetaData?: MetaData -): >( + rootMetaData?: MetaData, +): >( target: Target, ...objects: Ts ) => void { @@ -108,7 +110,7 @@ export function deepmergeIntoCustom< */ type CustomizedDeepmergeInto = < Target extends object, - Ts extends ReadonlyArray + Ts extends ReadonlyArray, >( target: Target, ...objects: Ts @@ -142,13 +144,13 @@ export function deepmergeIntoCustom< */ function getIntoUtils< M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( options: DeepMergeIntoOptions, customizedDeepmergeInto: DeepMergeMergeIntoFunctionUtils< M, MM - >["deepmergeInto"] + >["deepmergeInto"], ): DeepMergeMergeIntoFunctionUtils { return { defaultMergeFunctions: defaultMergeIntoFunctions, @@ -157,13 +159,13 @@ function getIntoUtils< ...Object.fromEntries( Object.entries(options) .filter(([key, option]) => - Object.hasOwn(defaultMergeIntoFunctions, key) + Object.hasOwn(defaultMergeIntoFunctions, key), ) .map(([key, option]) => option === false ? [key, defaultMergeIntoFunctions.mergeOthers] - : [key, option] - ) + : [key, option], + ), ), } as DeepMergeMergeIntoFunctionUtils["mergeFunctions"], metaDataUpdater: (options.metaDataUpdater ?? @@ -186,13 +188,13 @@ export function mergeUnknownsInto< Ts extends ReadonlyArray, U extends DeepMergeMergeIntoFunctionUtils, M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( m_target: Reference, values: Ts, utils: U, - meta: M | undefined - // eslint-disable-next-line @typescript-eslint/no-invalid-void-type + meta: M | undefined, + // eslint-disable-next-line ts/no-invalid-void-type ): void | symbol { if (values.length === 0) { return; @@ -219,7 +221,7 @@ export function mergeUnknownsInto< m_target as Reference>, values as ReadonlyArray>>, utils, - meta + meta, ); } @@ -228,7 +230,7 @@ export function mergeUnknownsInto< m_target as Reference, values as ReadonlyArray>, utils, - meta + meta, ); } @@ -237,7 +239,7 @@ export function mergeUnknownsInto< m_target as Reference>, values as ReadonlyArray>>, utils, - meta + meta, ); } @@ -246,7 +248,7 @@ export function mergeUnknownsInto< m_target as Reference>, values as ReadonlyArray>>, utils, - meta + meta, ); } @@ -265,18 +267,18 @@ export function mergeUnknownsInto< function mergeRecordsInto< U extends DeepMergeMergeIntoFunctionUtils, M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( m_target: Reference>, values: ReadonlyArray>>, utils: U, - meta: M | undefined + meta: M | undefined, ) { const action = utils.mergeFunctions.mergeRecords( m_target, values, utils, - meta + meta, ); if (action === actions.defaultMerge) { @@ -298,18 +300,18 @@ function mergeRecordsInto< function mergeArraysInto< U extends DeepMergeMergeIntoFunctionUtils, M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( m_target: Reference, values: ReadonlyArray>, utils: U, - meta: M | undefined + meta: M | undefined, ) { const action = utils.mergeFunctions.mergeArrays( m_target, values, utils, - meta + meta, ); if (action === actions.defaultMerge) { @@ -326,12 +328,12 @@ function mergeArraysInto< function mergeSetsInto< U extends DeepMergeMergeIntoFunctionUtils, M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( m_target: Reference>, values: ReadonlyArray>>, utils: U, - meta: M | undefined + meta: M | undefined, ) { const action = utils.mergeFunctions.mergeSets(m_target, values, utils, meta); @@ -349,12 +351,12 @@ function mergeSetsInto< function mergeMapsInto< U extends DeepMergeMergeIntoFunctionUtils, M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( m_target: Reference>, values: ReadonlyArray>>, utils: U, - meta: M | undefined + meta: M | undefined, ) { const action = utils.mergeFunctions.mergeMaps(m_target, values, utils, meta); @@ -372,18 +374,18 @@ function mergeMapsInto< function mergeOthersInto< U extends DeepMergeMergeIntoFunctionUtils, M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( m_target: Reference, values: ReadonlyArray, utils: U, - meta: M | undefined + meta: M | undefined, ) { const action = utils.mergeFunctions.mergeOthers( m_target, values, utils, - meta + meta, ); if ( diff --git a/dist/deno/deepmerge.ts b/dist/deno/deepmerge.ts index 8ad91449..ceeff141 100644 --- a/dist/deno/deepmerge.ts +++ b/dist/deno/deepmerge.ts @@ -4,13 +4,13 @@ import * as defaultMergeFunctions from "./defaults/vanilla.ts"; import { type DeepMergeBuiltInMetaData, type DeepMergeHKT, + type DeepMergeMergeFunctionUtils, type DeepMergeMergeFunctionsDefaultURIs, type DeepMergeMergeFunctionsURIs, type DeepMergeOptions, - type DeepMergeMergeFunctionUtils, type GetDeepMergeMergeFunctionsURIs, } from "./types/index.ts"; -import { getObjectType, ObjectType } from "./utils.ts"; +import { ObjectType, getObjectType } from "./utils.ts"; /** * Deeply merge objects. @@ -18,7 +18,6 @@ import { getObjectType, ObjectType } from "./utils.ts"; * @param objects - The objects to merge. */ export function deepmerge>>( - // eslint-disable-next-line functional/functional-parameters ...objects: readonly [...Ts] ): DeepMergeHKT< Ts, @@ -38,10 +37,11 @@ export function deepmerge>>( * @param options - The options on how to customize the merge function. */ export function deepmergeCustom< - PMF extends Partial + BaseTs = unknown, + PMF extends Partial = {}, >( - options: DeepMergeOptions -): >( + options: DeepMergeOptions, +): >( ...objects: Ts ) => DeepMergeHKT< Ts, @@ -56,24 +56,26 @@ export function deepmergeCustom< * @param rootMetaData - The meta data passed to the root items' being merged. */ export function deepmergeCustom< - PMF extends Partial, - MetaData, - MetaMetaData extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + BaseTs = unknown, + PMF extends Partial = {}, + MetaData = DeepMergeBuiltInMetaData, + MetaMetaData extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( options: DeepMergeOptions, - rootMetaData?: MetaData -): >( + rootMetaData?: MetaData, +): >( ...objects: Ts ) => DeepMergeHKT, MetaData>; export function deepmergeCustom< + BaseTs, PMF extends Partial, MetaData, - MetaMetaData extends DeepMergeBuiltInMetaData + MetaMetaData extends DeepMergeBuiltInMetaData, >( options: DeepMergeOptions, - rootMetaData?: MetaData -): >( + rootMetaData?: MetaData, +): >( ...objects: Ts ) => DeepMergeHKT, MetaData> { /** @@ -85,16 +87,13 @@ export function deepmergeCustom< const utils: DeepMergeMergeFunctionUtils = getUtils( options, - customizedDeepmerge as CustomizedDeepmerge + customizedDeepmerge as CustomizedDeepmerge, ); /** * The customized deepmerge function. */ - function customizedDeepmerge( - // eslint-disable-next-line functional/functional-parameters - ...objects: ReadonlyArray - ) { + function customizedDeepmerge(...objects: ReadonlyArray) { return mergeUnknowns< ReadonlyArray, typeof utils, @@ -114,10 +113,10 @@ export function deepmergeCustom< */ function getUtils< M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( options: DeepMergeOptions, - customizedDeepmerge: DeepMergeMergeFunctionUtils["deepmerge"] + customizedDeepmerge: DeepMergeMergeFunctionUtils["deepmerge"], ): DeepMergeMergeFunctionUtils { return { defaultMergeFunctions, @@ -129,8 +128,8 @@ function getUtils< .map(([key, option]) => option === false ? [key, defaultMergeFunctions.mergeOthers] - : [key, option] - ) + : [key, option], + ), ), } as DeepMergeMergeFunctionUtils["mergeFunctions"], metaDataUpdater: (options.metaDataUpdater ?? @@ -154,7 +153,7 @@ export function mergeUnknowns< U extends DeepMergeMergeFunctionUtils, MF extends DeepMergeMergeFunctionsURIs, M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >(values: Ts, utils: U, meta: M | undefined): DeepMergeHKT { if (values.length === 0) { return undefined as DeepMergeHKT; @@ -169,7 +168,6 @@ export function mergeUnknowns< const type = getObjectType(values[0]); - /* eslint-disable functional/no-loop-statements, functional/no-conditional-statements -- using imperative code here is more performant. */ if (type !== ObjectType.NOT && type !== ObjectType.OTHER) { for (let m_index = 1; m_index < values.length; m_index++) { if (getObjectType(values[m_index]) === type) { @@ -183,14 +181,13 @@ export function mergeUnknowns< >; } } - /* eslint-enable functional/no-loop-statements, functional/no-conditional-statements */ switch (type) { case ObjectType.RECORD: { return mergeRecords( values as ReadonlyArray>>, utils, - meta + meta, ) as DeepMergeHKT; } @@ -198,7 +195,7 @@ export function mergeUnknowns< return mergeArrays( values as ReadonlyArray>>, utils, - meta + meta, ) as DeepMergeHKT; } @@ -206,7 +203,7 @@ export function mergeUnknowns< return mergeSets( values as ReadonlyArray>>, utils, - meta + meta, ) as DeepMergeHKT; } @@ -214,7 +211,7 @@ export function mergeUnknowns< return mergeMaps( values as ReadonlyArray>>, utils, - meta + meta, ) as DeepMergeHKT; } @@ -237,11 +234,11 @@ function mergeRecords< U extends DeepMergeMergeFunctionUtils, MF extends DeepMergeMergeFunctionsURIs, M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( values: ReadonlyArray>>, utils: U, - meta: M | undefined + meta: M | undefined, ) { const result = utils.mergeFunctions.mergeRecords(values, utils, meta); @@ -272,11 +269,11 @@ function mergeRecords< function mergeArrays< U extends DeepMergeMergeFunctionUtils, M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( values: ReadonlyArray>>, utils: U, - meta: M | undefined + meta: M | undefined, ) { const result = utils.mergeFunctions.mergeArrays(values, utils, meta); @@ -300,11 +297,11 @@ function mergeArrays< function mergeSets< U extends DeepMergeMergeFunctionUtils, M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( values: ReadonlyArray>>, utils: U, - meta: M | undefined + meta: M | undefined, ) { const result = utils.mergeFunctions.mergeSets(values, utils, meta); @@ -327,11 +324,11 @@ function mergeSets< function mergeMaps< U extends DeepMergeMergeFunctionUtils, M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( values: ReadonlyArray>>, utils: U, - meta: M | undefined + meta: M | undefined, ) { const result = utils.mergeFunctions.mergeMaps(values, utils, meta); @@ -354,7 +351,7 @@ function mergeMaps< function mergeOthers< U extends DeepMergeMergeFunctionUtils, M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >(values: ReadonlyArray, utils: U, meta: M | undefined) { const result = utils.mergeFunctions.mergeOthers(values, utils, meta); diff --git a/dist/deno/defaults/into.ts b/dist/deno/defaults/into.ts index 9ee960bf..144b43a3 100644 --- a/dist/deno/defaults/into.ts +++ b/dist/deno/defaults/into.ts @@ -27,12 +27,12 @@ export function mergeRecords< Ts extends ReadonlyArray>, U extends DeepMergeMergeIntoFunctionUtils, M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( m_target: Reference>, values: Ts, utils: U, - meta: M | undefined + meta: M | undefined, ): void { for (const key of getKeys(values)) { const propValues = []; @@ -57,7 +57,7 @@ export function mergeRecords< propertyTarget, propValues, utils, - updatedMeta + updatedMeta, ); if (key === "__proto__") { @@ -81,7 +81,7 @@ export function mergeRecords< */ export function mergeArrays>>( m_target: Reference, - values: Ts + values: Ts, ): void { m_target.value.push(...values.slice(1).flat()); } @@ -93,7 +93,7 @@ export function mergeArrays>>( * @param values - The sets (including the target's value if there is one). */ export function mergeSets< - Ts extends ReadonlyArray>> + Ts extends ReadonlyArray>>, >(m_target: Reference>, values: Ts): void { for (const value of getIterableOfIterables(values.slice(1))) { m_target.value.add(value); @@ -107,7 +107,7 @@ export function mergeSets< * @param values - The maps (including the target's value if there is one). */ export function mergeMaps< - Ts extends ReadonlyArray>> + Ts extends ReadonlyArray>>, >(m_target: Reference>, values: Ts): void { for (const [key, value] of getIterableOfIterables(values.slice(1))) { m_target.value.set(key, value); @@ -115,11 +115,17 @@ export function mergeMaps< } /** - * Set the target to the last value. + * Set the target to the last non-undefined value. */ export function mergeOthers>( m_target: Reference, - values: Ts + values: Ts, ) { - m_target.value = values.at(-1); + for (let i = values.length - 1; i >= 0; i--) { + if (values[i] !== undefined) { + m_target.value = values[i]; + return; + } + } + m_target.value = undefined; } diff --git a/dist/deno/defaults/meta-data-updater.ts b/dist/deno/defaults/meta-data-updater.ts index 2b392149..1b9432c3 100644 --- a/dist/deno/defaults/meta-data-updater.ts +++ b/dist/deno/defaults/meta-data-updater.ts @@ -5,7 +5,7 @@ import { type DeepMergeBuiltInMetaData } from "../types/index.ts"; */ export function defaultMetaDataUpdater( previousMeta: M, - metaMeta: DeepMergeBuiltInMetaData + metaMeta: DeepMergeBuiltInMetaData, ): DeepMergeBuiltInMetaData { return metaMeta; } diff --git a/dist/deno/defaults/vanilla.ts b/dist/deno/defaults/vanilla.ts index d8aeef9c..decd60cd 100644 --- a/dist/deno/defaults/vanilla.ts +++ b/dist/deno/defaults/vanilla.ts @@ -4,12 +4,12 @@ import { type DeepMergeArraysDefaultHKT, type DeepMergeBuiltInMetaData, type DeepMergeMapsDefaultHKT, - type DeepMergeMergeFunctionsURIs, type DeepMergeMergeFunctionUtils, + type DeepMergeMergeFunctionsURIs, type DeepMergeRecordsDefaultHKT, type DeepMergeSetsDefaultHKT, } from "../types/index.ts"; -import { getKeys, objectHasProperty, getIterableOfIterables } from "../utils.ts"; +import { getIterableOfIterables, getKeys, objectHasProperty } from "../utils.ts"; /** * The default merge functions. @@ -32,16 +32,14 @@ export function mergeRecords< U extends DeepMergeMergeFunctionUtils, MF extends DeepMergeMergeFunctionsURIs, M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, >( values: Ts, utils: U, - meta: M | undefined + meta: M | undefined, ): DeepMergeRecordsDefaultHKT { const result: Record = {}; - /* eslint-disable functional/no-loop-statements, functional/no-conditional-statements, functional/no-expression-statements, functional/immutable-data -- using imperative code here is more performant. */ - for (const key of getKeys(values)) { const propValues = []; @@ -63,7 +61,7 @@ export function mergeRecords< const propertyResult = mergeUnknowns, U, MF, M, MM>( propValues, utils, - updatedMeta + updatedMeta, ); if (propertyResult === actions.skip) { @@ -82,8 +80,6 @@ export function mergeRecords< } } - /* eslint-enable functional/no-loop-statements, functional/no-conditional-statements, functional/no-expression-statements, functional/immutable-data */ - return result as DeepMergeRecordsDefaultHKT; } @@ -95,7 +91,7 @@ export function mergeRecords< export function mergeArrays< Ts extends ReadonlyArray>, MF extends DeepMergeMergeFunctionsURIs, - M + M, >(values: Ts): DeepMergeArraysDefaultHKT { return values.flat() as DeepMergeArraysDefaultHKT; } @@ -106,7 +102,7 @@ export function mergeArrays< * @param values - The sets. */ export function mergeSets< - Ts extends ReadonlyArray>> + Ts extends ReadonlyArray>>, >(values: Ts): DeepMergeSetsDefaultHKT { return new Set(getIterableOfIterables(values)) as DeepMergeSetsDefaultHKT; } @@ -117,14 +113,19 @@ export function mergeSets< * @param values - The maps. */ export function mergeMaps< - Ts extends ReadonlyArray>> + Ts extends ReadonlyArray>>, >(values: Ts): DeepMergeMapsDefaultHKT { return new Map(getIterableOfIterables(values)) as DeepMergeMapsDefaultHKT; } /** - * Get the last value in the given array. + * Get the last non-undefined value in the given array. */ export function mergeOthers>(values: Ts) { - return values.at(-1); + for (let i = values.length - 1; i >= 0; i--) { + if (values[i] !== undefined) { + return values[i]; + } + } + return undefined; } diff --git a/dist/deno/index.ts b/dist/deno/index.ts index 377dff8e..cd408d1a 100644 --- a/dist/deno/index.ts +++ b/dist/deno/index.ts @@ -14,7 +14,6 @@ export type { DeepMergeBuiltInMetaData, DeepMergeHKT, DeepMergeLeaf, - DeepMergeLeafHKT, DeepMergeLeafURI, DeepMergeMapsDefaultHKT, DeepMergeMergeFunctionsDefaultURIs, diff --git a/dist/deno/types/defaults.ts b/dist/deno/types/defaults.ts index d37d3303..53b565af 100644 --- a/dist/deno/types/defaults.ts +++ b/dist/deno/types/defaults.ts @@ -1,18 +1,19 @@ import { type DeepMergeHKT, type DeepMergeLeafURI, - type DeepMergeMergeFunctionsURIs, type DeepMergeMergeFunctionURItoKind, + type DeepMergeMergeFunctionsURIs, } from "./merging.ts"; import { - type FlatternAlias, type FilterOutNever, - type OptionalKeysOf, - type RequiredKeysOf, + type FlattenTuples, + type SimplifyObject, + type TransposeTuple, + type TupleToIntersection, + type TuplifyUnion, type UnionMapKeys, type UnionMapValues, type UnionSetValues, - type ValueOfKey, } from "./utils.ts"; /** @@ -46,11 +47,37 @@ export type DeepMergeMergeFunctionsDefaultURIs = Readonly<{ DeepMergeOthersURI: DeepMergeLeafURI; }>; -/** - * A union of all the props that should not be included in type information for - * merged records. - */ -type BlacklistedRecordProps = "__proto__"; +type RecordEntries> = TuplifyUnion< + { + [K in keyof T]: [K, T[K]]; + }[keyof T] +>; + +type RecordMeta = Record; + +type RecordPropertyMeta< + Key extends PropertyKey = PropertyKey, + Value = unknown, + Optional extends boolean = boolean, +> = { + key: Key; + value: Value; + optional: Optional; +}; + +type RecordsToRecordMeta< + Ts extends ReadonlyArray>, +> = { + [I in keyof Ts]: RecordToRecordMeta; +}; + +type RecordToRecordMeta> = { + [K in keyof T]-?: { + key: K; + value: Required[K]; + optional: {} extends Pick ? true : false; + }; +}; /** * Deep merge records. @@ -58,77 +85,176 @@ type BlacklistedRecordProps = "__proto__"; export type DeepMergeRecordsDefaultHKT< Ts extends ReadonlyArray, MF extends DeepMergeMergeFunctionsURIs, - M -> = Ts extends Readonly>]> - ? FlatternAlias< - Omit< - DeepMergeRecordsDefaultHKTInternalProps, - BlacklistedRecordProps + M, +> = + Ts extends ReadonlyArray> + ? SimplifyObject< + DeepMergeRecordMetaDefaultHKTProps, MF, M> > - > - : {}; + : never; /** * Deep merge record props. */ -type DeepMergeRecordsDefaultHKTInternalProps< - Ts extends readonly [unknown, ...ReadonlyArray], +type DeepMergeRecordMetaDefaultHKTProps< + RecordMetas extends ReadonlyArray, MF extends DeepMergeMergeFunctionsURIs, - M -> = { - [K in OptionalKeysOf]?: DeepMergeHKT< - DeepMergeRecordsDefaultHKTInternalPropValue, - MF, - M - >; -} & { - [K in RequiredKeysOf]: DeepMergeHKT< - DeepMergeRecordsDefaultHKTInternalPropValue, - MF, - M + M, +> = CreateRecordFromMeta, MF, M>; + +type MergeRecordMeta> = + GroupValuesByKey< + FlattenTuples< + TransposeTuple<{ + [I in keyof RecordMetas]: TransposeTuple>; + }> + > >; -}; + +type GroupValuesByKey = Ts extends readonly [ + infer Keys extends ReadonlyArray, + infer Values, +] + ? { + [I in keyof Keys]: DeepMergeRecordPropertyMetaDefaultHKTGetPossible< + Keys[I], + FilterOutNever<{ + [J in keyof Values]: Values[J] extends { + key: Keys[I]; + } + ? Values[J] + : never; + }> + >; + } + : never; + +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; + }> + : never; + +type CreateRecordForKeyFromMeta< + Key extends PropertyKey, + Values extends ReadonlyArray, + Optional extends boolean, + MF extends DeepMergeMergeFunctionsURIs, + M, +> = Optional extends true + ? { + [k in Key]+?: DeepMergeHKT; + } + : { + [k in Key]-?: DeepMergeHKT; + }; /** - * Get the value of the property. + * Get the possible types of a property. */ -type DeepMergeRecordsDefaultHKTInternalPropValue< - Ts extends readonly [unknown, ...ReadonlyArray], - K extends PropertyKey, - M -> = FilterOutNever< - DeepMergeRecordsDefaultHKTInternalPropValueHelper ->; +type DeepMergeRecordPropertyMetaDefaultHKTGetPossible< + Key extends PropertyKey, + Ts, +> = Ts extends readonly [ + RecordPropertyMeta, + ...ReadonlyArray, +] + ? DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper< + Ts, + { key: Key; values: []; optional: never } + > + : never; /** - * Tail-recursive helper type for DeepMergeRecordsDefaultHKTInternalPropValue. + * Tail-recursive helper type for DeepMergeRecordPropertyMetaDefaultHKTGetPossible. */ -type DeepMergeRecordsDefaultHKTInternalPropValueHelper< - Ts extends readonly [unknown, ...ReadonlyArray], - K extends PropertyKey, - M, - Acc extends ReadonlyArray -> = Ts extends readonly [ - infer Head extends Readonly>, - ...infer Rest +type DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper< + Ts extends readonly [ + RecordPropertyMeta, + ...ReadonlyArray, + ], + Acc extends { + key: PropertyKey; + values: ReadonlyArray; + optional: boolean; + }, +> = Ts extends [ + ...infer Rest, + { + key: infer K extends PropertyKey; + value: infer V; + optional: infer O extends boolean; + }, ] - ? Rest extends readonly [unknown, ...ReadonlyArray] - ? DeepMergeRecordsDefaultHKTInternalPropValueHelper< - Rest, - K, - M, - [...Acc, ValueOfKey] - > - : [...Acc, ValueOfKey] + ? Acc["optional"] extends true + ? Acc extends { values: [infer Head, ...infer AccRest] } + ? Rest extends readonly [ + RecordPropertyMeta, + ...ReadonlyArray, + ] + ? DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper< + Rest, + { + key: K; + values: [V | Head, ...AccRest]; + optional: O; + } + > + : { + key: K; + values: [V | Head, ...AccRest]; + optional: O; + } + : Rest extends readonly [ + RecordPropertyMeta, + ...ReadonlyArray, + ] + ? DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper< + Rest, + { + key: K; + values: [V, ...Acc["values"]]; + optional: O; + } + > + : { + key: K; + values: [V, ...Acc["values"]]; + optional: O; + } + : Rest extends readonly [ + RecordPropertyMeta, + ...ReadonlyArray, + ] + ? DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper< + Rest, + { + key: K; + values: [V, ...Acc["values"]]; + optional: O; + } + > + : { + key: K; + values: [V, ...Acc["values"]]; + optional: O; + } : never; /** - * Deep merge 2 arrays. + * Deep merge arrays. */ export type DeepMergeArraysDefaultHKT< Ts extends ReadonlyArray, MF extends DeepMergeMergeFunctionsURIs, - M + M, > = DeepMergeArraysDefaultHKTHelper; /** @@ -138,28 +264,28 @@ type DeepMergeArraysDefaultHKTHelper< Ts extends ReadonlyArray, MF extends DeepMergeMergeFunctionsURIs, M, - Acc extends ReadonlyArray + Acc extends ReadonlyArray, > = Ts extends readonly [ infer Head extends ReadonlyArray, - ...infer Rest + ...infer Rest, ] ? Rest extends readonly [ ReadonlyArray, - ...ReadonlyArray> + ...ReadonlyArray>, ] ? DeepMergeArraysDefaultHKTHelper : [...Acc, ...Head] : never; /** - * Deep merge 2 sets. + * Deep merge sets. */ export type DeepMergeSetsDefaultHKT> = Set< UnionSetValues >; /** - * Deep merge 2 maps. + * Deep merge maps. */ export type DeepMergeMapsDefaultHKT> = Map< UnionMapKeys, @@ -170,39 +296,34 @@ export type DeepMergeMapsDefaultHKT> = Map< * Get the merge functions with defaults apply from the given subset. */ export type GetDeepMergeMergeFunctionsURIs< - PMF extends Partial + PMF extends Partial, > = Readonly<{ // prettier-ignore DeepMergeRecordsURI: - // eslint-disable-next-line @typescript-eslint/no-explicit-any PMF["DeepMergeRecordsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeRecordsURI"] : DeepMergeRecordsDefaultURI; // prettier-ignore DeepMergeArraysURI: - // eslint-disable-next-line @typescript-eslint/no-explicit-any PMF["DeepMergeArraysURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeArraysURI"] : DeepMergeArraysDefaultURI; // prettier-ignore DeepMergeSetsURI: - // eslint-disable-next-line @typescript-eslint/no-explicit-any PMF["DeepMergeSetsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeSetsURI"] : DeepMergeSetsDefaultURI; // prettier-ignore DeepMergeMapsURI: - // eslint-disable-next-line @typescript-eslint/no-explicit-any PMF["DeepMergeMapsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeMapsURI"] : DeepMergeMapsDefaultURI; // prettier-ignore DeepMergeOthersURI: - // eslint-disable-next-line @typescript-eslint/no-explicit-any PMF["DeepMergeOthersURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeOthersURI"] : DeepMergeLeafURI; diff --git a/dist/deno/types/merging.ts b/dist/deno/types/merging.ts index 27a0e88b..9ccda959 100644 --- a/dist/deno/types/merging.ts +++ b/dist/deno/types/merging.ts @@ -1,26 +1,28 @@ import { - type DeepMergeRecordsDefaultHKT, type DeepMergeArraysDefaultHKT, - type DeepMergeSetsDefaultHKT, type DeepMergeMapsDefaultHKT, + type DeepMergeRecordsDefaultHKT, + type DeepMergeSetsDefaultHKT, } from "./defaults.ts"; import { type EveryIsArray, 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 @typescript-eslint/consistent-type-definitions +// eslint-disable-next-line ts/consistent-type-definitions export interface DeepMergeMergeFunctionURItoKind< Ts extends ReadonlyArray, MF extends DeepMergeMergeFunctionsURIs, - in out M + in out M, > { readonly DeepMergeLeafURI: DeepMergeLeaf; readonly DeepMergeRecordsDefaultURI: DeepMergeRecordsDefaultHKT; @@ -36,7 +38,7 @@ type DeepMergeMergeFunctionKind< URI extends DeepMergeMergeFunctionURIs, Ts extends ReadonlyArray, MF extends DeepMergeMergeFunctionsURIs, - M + M, > = DeepMergeMergeFunctionURItoKind[URI]; /** @@ -84,22 +86,23 @@ export type DeepMergeMergeFunctionsURIs = Readonly<{ export type DeepMergeHKT< Ts extends ReadonlyArray, MF extends DeepMergeMergeFunctionsURIs, - 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 - : unknown; + 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 + : unknown; /** * Deep merge records. @@ -107,7 +110,7 @@ export type DeepMergeHKT< type DeepMergeRecordsHKT< Ts extends ReadonlyArray, MF extends DeepMergeMergeFunctionsURIs, - M + M, > = DeepMergeMergeFunctionKind; /** @@ -116,7 +119,7 @@ type DeepMergeRecordsHKT< type DeepMergeArraysHKT< Ts extends ReadonlyArray, MF extends DeepMergeMergeFunctionsURIs, - M + M, > = DeepMergeMergeFunctionKind; /** @@ -125,7 +128,7 @@ type DeepMergeArraysHKT< type DeepMergeSetsHKT< Ts extends ReadonlyArray, MF extends DeepMergeMergeFunctionsURIs, - M + M, > = DeepMergeMergeFunctionKind; /** @@ -134,7 +137,7 @@ type DeepMergeSetsHKT< type DeepMergeMapsHKT< Ts extends ReadonlyArray, MF extends DeepMergeMergeFunctionsURIs, - M + M, > = DeepMergeMergeFunctionKind; /** @@ -143,7 +146,7 @@ type DeepMergeMapsHKT< type DeepMergeOthersHKT< Ts extends ReadonlyArray, MF extends DeepMergeMergeFunctionsURIs, - M + M, > = DeepMergeMergeFunctionKind; /** @@ -151,14 +154,6 @@ type DeepMergeOthersHKT< */ export type DeepMergeLeafURI = "DeepMergeLeafURI"; -/** - * Get the leaf type from many types that can't be merged. - * - * @deprecated Use `DeepMergeLeaf` instead. - */ -export type DeepMergeLeafHKT> = - DeepMergeLeaf; - /** * Get the leaf type from many types that can't be merged. */ @@ -166,14 +161,14 @@ export type DeepMergeLeaf> = Ts extends readonly [] ? never : Ts extends readonly [infer T] - ? T - : Ts extends readonly [...infer Rest, infer Tail] - ? IsNever extends true - ? Rest extends ReadonlyArray - ? DeepMergeLeaf - : never - : Tail - : never; + ? T + : Ts extends readonly [...infer Rest, infer Tail] + ? Or, Is> extends true + ? Rest extends ReadonlyArray + ? DeepMergeLeaf + : never + : Tail + : never; /** * The meta data deepmerge is able to provide. diff --git a/dist/deno/types/options.ts b/dist/deno/types/options.ts index 930d0a70..15ecf706 100644 --- a/dist/deno/types/options.ts +++ b/dist/deno/types/options.ts @@ -8,7 +8,7 @@ import { type DeepMergeBuiltInMetaData } from "./merging.ts"; */ export type DeepMergeOptions< in out M, - MM extends Readonly> = {} + MM extends Readonly> = {}, > = Partial>; /** @@ -16,12 +16,12 @@ export type DeepMergeOptions< */ export type DeepMergeIntoOptions< in out M, - MM extends Readonly> = {} + MM extends Readonly> = {}, > = Partial>; type MetaDataUpdater< in out M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, > = (previousMeta: M | undefined, metaMeta: Readonly>) => M; /** @@ -29,7 +29,7 @@ type MetaDataUpdater< */ type DeepMergeOptionsFull< in out M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, > = Readonly<{ mergeRecords: DeepMergeMergeFunctions["mergeRecords"] | false; mergeArrays: DeepMergeMergeFunctions["mergeArrays"] | false; @@ -45,7 +45,7 @@ type DeepMergeOptionsFull< */ type DeepMergeIntoOptionsFull< in out M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, > = Readonly<{ mergeRecords: DeepMergeMergeIntoFunctions["mergeRecords"] | false; mergeArrays: DeepMergeMergeIntoFunctions["mergeArrays"] | false; @@ -67,55 +67,55 @@ export type Reference = { */ type DeepMergeMergeFunctions< in M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, > = Readonly<{ mergeRecords: < Ts extends ReadonlyArray>>, - U extends DeepMergeMergeFunctionUtils + U extends DeepMergeMergeFunctionUtils, >( values: Ts, utils: U, - meta: M | undefined + meta: M | undefined, ) => unknown; mergeArrays: < Ts extends ReadonlyArray>, - U extends DeepMergeMergeFunctionUtils + U extends DeepMergeMergeFunctionUtils, >( values: Ts, utils: U, - meta: M | undefined + meta: M | undefined, ) => unknown; mergeMaps: < Ts extends ReadonlyArray>>, - U extends DeepMergeMergeFunctionUtils + U extends DeepMergeMergeFunctionUtils, >( values: Ts, utils: U, - meta: M | undefined + meta: M | undefined, ) => unknown; mergeSets: < Ts extends ReadonlyArray>>, - U extends DeepMergeMergeFunctionUtils + U extends DeepMergeMergeFunctionUtils, >( values: Ts, utils: U, - meta: M | undefined + meta: M | undefined, ) => unknown; mergeOthers: < Ts extends ReadonlyArray, - U extends DeepMergeMergeFunctionUtils + U extends DeepMergeMergeFunctionUtils, >( values: Ts, utils: U, - meta: M | undefined + meta: M | undefined, ) => unknown; }>; -// eslint-disable-next-line @typescript-eslint/no-invalid-void-type +// eslint-disable-next-line ts/no-invalid-void-type type DeepMergeMergeIntoFunctionsReturnType = void | symbol; /** @@ -123,56 +123,56 @@ type DeepMergeMergeIntoFunctionsReturnType = void | symbol; */ type DeepMergeMergeIntoFunctions< in M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, > = Readonly<{ mergeRecords: < Ts extends ReadonlyArray>>, - U extends DeepMergeMergeIntoFunctionUtils + U extends DeepMergeMergeIntoFunctionUtils, >( m_target: Reference>, values: Ts, utils: U, - meta: M | undefined + meta: M | undefined, ) => DeepMergeMergeIntoFunctionsReturnType; mergeArrays: < Ts extends ReadonlyArray>, - U extends DeepMergeMergeIntoFunctionUtils + U extends DeepMergeMergeIntoFunctionUtils, >( m_target: Reference, values: Ts, utils: U, - meta: M | undefined + meta: M | undefined, ) => DeepMergeMergeIntoFunctionsReturnType; mergeMaps: < Ts extends ReadonlyArray>>, - U extends DeepMergeMergeIntoFunctionUtils + U extends DeepMergeMergeIntoFunctionUtils, >( m_target: Reference>, values: Ts, utils: U, - meta: M | undefined + meta: M | undefined, ) => DeepMergeMergeIntoFunctionsReturnType; mergeSets: < Ts extends ReadonlyArray>>, - U extends DeepMergeMergeIntoFunctionUtils + U extends DeepMergeMergeIntoFunctionUtils, >( m_target: Reference>, values: Ts, utils: U, - meta: M | undefined + meta: M | undefined, ) => DeepMergeMergeIntoFunctionsReturnType; mergeOthers: < Ts extends ReadonlyArray, - U extends DeepMergeMergeIntoFunctionUtils + U extends DeepMergeMergeIntoFunctionUtils, >( m_target: Reference, values: Ts, utils: U, - meta: M | undefined + meta: M | undefined, ) => DeepMergeMergeIntoFunctionsReturnType; }>; @@ -181,7 +181,7 @@ type DeepMergeMergeIntoFunctions< */ export type DeepMergeMergeFunctionUtils< in out M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, > = Readonly<{ mergeFunctions: DeepMergeMergeFunctions; defaultMergeFunctions: MergeFunctions; @@ -197,10 +197,9 @@ export type DeepMergeMergeFunctionUtils< /** * The utils provided to the merge functions. */ -// eslint-disable-next-line functional/no-mixed-types export type DeepMergeMergeIntoFunctionUtils< in out M, - MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData + MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData, > = Readonly<{ mergeFunctions: DeepMergeMergeIntoFunctions; defaultMergeFunctions: MergeIntoFunctions; @@ -208,7 +207,7 @@ export type DeepMergeMergeIntoFunctionUtils< deepmergeInto: >( target: Target, ...values: Ts - ) => void; // eslint-disable-line functional/no-return-void + ) => void; actions: Readonly<{ defaultMerge: symbol; }>; diff --git a/dist/deno/types/utils.ts b/dist/deno/types/utils.ts index 61fcf2ca..dd9e8bed 100644 --- a/dist/deno/types/utils.ts +++ b/dist/deno/types/utils.ts @@ -1,18 +1,28 @@ /** - * Flatten a complex type such as a union or intersection of objects into a + * Simplify a complex type such as a union or intersection of objects into a * single object. */ -export type FlatternAlias = Is extends true - ? T - : { [P in keyof T]: T[P] } & {}; +export type SimplifyObject = { + [K in keyof T]: T[K]; +} & {}; /** - * Get the value of the given key in the given object. + * Flatten a collection of tuples of tuples into a collection of tuples. */ -export type ValueOfKey< - T extends Record, - K extends PropertyKey -> = K extends keyof T ? T[K] : never; +export type FlattenTuples = { + [I in keyof T]: FlattenTuple; +}; + +/** + * Flatten a tuple of tuples into a single tuple. + */ +export type FlattenTuple = T extends readonly [] + ? [] + : T extends readonly [infer T0] + ? [...FlattenTuple] + : T extends readonly [infer T0, ...infer Ts] + ? [...FlattenTuple, ...FlattenTuple] + : [T]; /** * Safely test whether or not the first given types extends the second. @@ -26,6 +36,25 @@ export type Is = [T1] extends [T2] ? true : false; */ export type IsNever = Is; +/** + * And operator for types. + */ +export type And = T1 extends false + ? false + : T2; + +/** + * Or operator for types. + */ +export type Or = T1 extends true + ? true + : T2; + +/** + * Not operator for types. + */ +export type Not = T extends true ? false : true; + /** * Returns whether or not all the given types are never. */ @@ -73,12 +102,12 @@ export type EveryIsArray> = Ts extends readonly [infer T1] ? IsArray : Ts extends readonly [infer Head, ...infer Rest] - ? IsArray extends true - ? Rest extends readonly [unknown, ...ReadonlyArray] - ? EveryIsArray + ? IsArray extends true + ? Rest extends readonly [unknown, ...ReadonlyArray] + ? EveryIsArray + : false : false - : false - : false; + : false; /** * Returns whether or not the given type is an set. @@ -95,17 +124,16 @@ export type IsSet = And< * * Note: This may also return true if all are maps. */ -export type EveryIsSet> = Ts extends Readonly< - readonly [infer T1] -> - ? IsSet - : Ts extends readonly [infer Head, ...infer Rest] - ? IsSet extends true - ? Rest extends readonly [unknown, ...ReadonlyArray] - ? EveryIsSet - : false - : false - : false; +export type EveryIsSet> = + Ts extends Readonly + ? IsSet + : Ts extends readonly [infer Head, ...infer Rest] + ? IsSet extends true + ? Rest extends readonly [unknown, ...ReadonlyArray] + ? EveryIsSet + : false + : false + : false; /** * Returns whether or not the given type is an map. @@ -118,36 +146,16 @@ export type IsMap = And< /** * Returns whether or not all the given types are maps. */ -export type EveryIsMap> = Ts extends Readonly< - readonly [infer T1] -> - ? IsMap - : Ts extends readonly [infer Head, ...infer Rest] - ? IsMap extends true - ? Rest extends readonly [unknown, ...ReadonlyArray] - ? EveryIsMap - : false - : false - : false; - -/** - * And operator for types. - */ -export type And = T1 extends false - ? false - : T2; - -/** - * Or operator for types. - */ -export type Or = T1 extends true - ? true - : T2; - -/** - * Not operator for types. - */ -export type Not = T extends true ? false : true; +export type EveryIsMap> = + Ts extends Readonly + ? IsMap + : Ts extends readonly [infer Head, ...infer Rest] + ? IsMap extends true + ? Rest extends readonly [unknown, ...ReadonlyArray] + ? EveryIsMap + : false + : false + : false; /** * Union of the sets' values' types @@ -160,7 +168,7 @@ export type UnionSetValues> = */ type UnionSetValuesHelper< Ts extends ReadonlyArray, - Acc + Acc, > = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Readonly> ? Rest extends ReadonlyArray @@ -180,7 +188,7 @@ export type UnionMapKeys> = */ type UnionMapKeysHelper< Ts extends ReadonlyArray, - Acc + Acc, > = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Readonly> ? Rest extends readonly [] @@ -200,7 +208,7 @@ export type UnionMapValues> = */ type UnionMapValuesHelper< Ts extends ReadonlyArray, - Acc + Acc, > = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Readonly> ? Rest extends readonly [] @@ -209,106 +217,25 @@ type UnionMapValuesHelper< : never : Acc; -/** - * Get all the keys of the given records. - */ -export type KeysOf> = KeysOfHelper; - -/** - * Tail-recursive helper type for KeysOf. - */ -type KeysOfHelper< - Ts extends ReadonlyArray, - Acc -> = Ts extends readonly [infer Head, ...infer Rest] - ? Head extends Record - ? Rest extends ReadonlyArray - ? KeysOfHelper - : Acc | keyof Head - : never - : Acc; - -/** - * Get the keys of the type what match a certain criteria. - */ -type KeysOfType = { - [K in keyof T]: T[K] extends U ? K : never; -}[keyof T]; - -/** - * Get the required keys of the type. - */ -type RequiredKeys = Exclude< - KeysOfType>, - undefined ->; - -/** - * Get all the required keys on the types in the tuple. - */ -export type RequiredKeysOf< - Ts extends readonly [unknown, ...ReadonlyArray] -> = RequiredKeysOfHelper; - -/** - * Tail-recursive helper type for RequiredKeysOf. - */ -type RequiredKeysOfHelper< - Ts extends readonly [unknown, ...ReadonlyArray], - Acc -> = Ts extends readonly [infer Head, ...infer Rest] - ? Head extends Record - ? Rest extends readonly [unknown, ...ReadonlyArray] - ? RequiredKeysOfHelper> - : Acc | RequiredKeys - : never - : Acc; - -/** - * Get the optional keys of the type. - */ -type OptionalKeys = Exclude>; - -/** - * Get all the optional keys on the types in the tuple. - */ -export type OptionalKeysOf< - Ts extends readonly [unknown, ...ReadonlyArray] -> = OptionalKeysOfHelper; - -/** - * Tail-recursive helper type for OptionalKeysOf. - */ -type OptionalKeysOfHelper< - Ts extends readonly [unknown, ...ReadonlyArray], - Acc -> = Ts extends readonly [infer Head, ...infer Rest] - ? Head extends Record - ? Rest extends readonly [unknown, ...ReadonlyArray] - ? OptionalKeysOfHelper> - : Acc | OptionalKeys - : never - : Acc; - /** * Filter out nevers from a tuple. */ -export type FilterOutNever> = - FilterOutNeverHelper; +export type FilterOutNever = + T extends ReadonlyArray ? FilterOutNeverHelper : never; /** * Tail-recursive helper type for FilterOutNever. */ type FilterOutNeverHelper< T extends ReadonlyArray, - Acc extends ReadonlyArray + Acc extends ReadonlyArray, > = T extends readonly [] ? Acc : T extends readonly [infer Head, ...infer Rest] - ? IsNever extends true - ? FilterOutNeverHelper - : FilterOutNeverHelper - : T; + ? IsNever extends true + ? FilterOutNeverHelper + : FilterOutNeverHelper + : T; /** * Is the type a tuple? @@ -316,5 +243,77 @@ type FilterOutNeverHelper< export type IsTuple> = T extends readonly [] ? true : T extends readonly [unknown, ...ReadonlyArray] - ? true - : false; + ? true + : false; + +/** + * Perfrom a transpose operation on a 2D tuple. + */ +export type TransposeTuple = T extends readonly [ + ...(readonly [...unknown[]]), +] + ? T extends readonly [] + ? [] + : T extends readonly [infer X extends ReadonlyArray] + ? TransposeTupleSimpleCase + : T extends readonly [ + infer X extends ReadonlyArray, + ...infer XS extends ReadonlyArray>, + ] + ? PrependCol> + : T + : never; + +type PrependCol< + T extends ReadonlyArray, + S extends ReadonlyArray>, +> = T extends readonly [] + ? S extends readonly [] + ? [] + : never + : T extends readonly [infer X, ...infer XS] + ? S extends readonly [ + readonly [...infer Y], + ...infer YS extends ReadonlyArray>, + ] + ? [[X, ...Y], ...PrependCol] + : never + : never; + +type TransposeTupleSimpleCase = + T extends readonly [] + ? [] + : T extends readonly [infer X, ...infer XS] + ? [[X], ...TransposeTupleSimpleCase] + : never; + +/** + * Convert a tuple to an intersection of each of its types. + */ +export type TupleToIntersection> = + { + [K in keyof T]: (x: T[K]) => void; + } extends Record void> + ? I + : never; + +/** + * Convert a union to a tuple. + * + * Warning: The order of the elements is non-deterministic. + * Warning 2: The union maybe me modified by the TypeScript engine before convertion. + * Warning 3: This implementation relies on a hack/limitation in TypeScript. + */ +export type TuplifyUnion> = + IsNever extends true ? [] : [...TuplifyUnion>, L]; + +type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ( + k: infer I, +) => void + ? I + : never; + +type LastOf = + UnionToIntersection T : never> extends () => infer R + ? R + : never; diff --git a/dist/deno/utils.ts b/dist/deno/utils.ts index 399f862a..a8fc2756 100644 --- a/dist/deno/utils.ts +++ b/dist/deno/utils.ts @@ -51,7 +51,6 @@ export function getObjectType(object: unknown): ObjectType { export function getKeys(objects: ReadonlyArray): Set { const keys = new Set(); - /* eslint-disable functional/no-loop-statements, functional/no-expression-statements -- using a loop here is more efficient. */ for (const object of objects) { for (const key of [ ...Object.keys(object), @@ -60,7 +59,6 @@ export function getKeys(objects: ReadonlyArray): Set { keys.add(key); } } - /* eslint-enable functional/no-loop-statements, functional/no-expression-statements */ return keys; } @@ -74,7 +72,7 @@ export function getKeys(objects: ReadonlyArray): Set { */ export function objectHasProperty( object: object, - property: PropertyKey + property: PropertyKey, ): boolean { return ( typeof object === "object" && @@ -86,14 +84,11 @@ export function objectHasProperty( * Get an iterable object that iterates over the given iterables. */ export function getIterableOfIterables( - iterables: ReadonlyArray>> + iterables: ReadonlyArray>>, ): Iterable { return { - // eslint-disable-next-line functional/functional-parameters *[Symbol.iterator]() { - // eslint-disable-next-line functional/no-loop-statements for (const iterable of iterables) { - // eslint-disable-next-line functional/no-loop-statements for (const value of iterable) { yield value; } @@ -119,12 +114,11 @@ function isRecord(value: object): value is Record { const { constructor } = value; // If has modified constructor. - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + // eslint-disable-next-line ts/no-unnecessary-condition if (constructor === undefined) { return true; } - // eslint-disable-next-line prefer-destructuring const prototype: unknown = constructor.prototype; // If has modified prototype. @@ -137,7 +131,7 @@ function isRecord(value: object): value is Record { } // If constructor does not have an Object-specific method. - // eslint-disable-next-line sonarjs/prefer-single-boolean-return, no-prototype-builtins + // eslint-disable-next-line sonar/prefer-single-boolean-return, no-prototype-builtins if (!prototype.hasOwnProperty("isPrototypeOf")) { return false; } diff --git a/dist/node/index.cjs b/dist/node/index.cjs index 78acaeb1..b9ea4df5 100644 --- a/dist/node/index.cjs +++ b/dist/node/index.cjs @@ -21,6 +21,18 @@ function defaultMetaDataUpdater(previousMeta, metaMeta) { return metaMeta; } +/** + * The different types of objects deepmerge-ts support. + */ +var ObjectType; +(function (ObjectType) { + ObjectType[ObjectType["NOT"] = 0] = "NOT"; + ObjectType[ObjectType["RECORD"] = 1] = "RECORD"; + ObjectType[ObjectType["ARRAY"] = 2] = "ARRAY"; + ObjectType[ObjectType["SET"] = 3] = "SET"; + ObjectType[ObjectType["MAP"] = 4] = "MAP"; + ObjectType[ObjectType["OTHER"] = 5] = "OTHER"; +})(ObjectType || (ObjectType = {})); /** * Get the type of the given object. * @@ -55,7 +67,6 @@ function getObjectType(object) { */ function getKeys(objects) { const keys = new Set(); - /* eslint-disable functional/no-loop-statements, functional/no-expression-statements -- using a loop here is more efficient. */ for (const object of objects) { for (const key of [ ...Object.keys(object), @@ -64,7 +75,6 @@ function getKeys(objects) { keys.add(key); } } - /* eslint-enable functional/no-loop-statements, functional/no-expression-statements */ return keys; } /** @@ -83,11 +93,8 @@ function objectHasProperty(object, property) { */ function getIterableOfIterables(iterables) { return { - // eslint-disable-next-line functional/functional-parameters *[Symbol.iterator]() { - // eslint-disable-next-line functional/no-loop-statements for (const iterable of iterables) { - // eslint-disable-next-line functional/no-loop-statements for (const value of iterable) { yield value; } @@ -109,11 +116,10 @@ function isRecord(value) { } const { constructor } = value; // If has modified constructor. - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + // eslint-disable-next-line ts/no-unnecessary-condition if (constructor === undefined) { return true; } - // eslint-disable-next-line prefer-destructuring const prototype = constructor.prototype; // If has modified prototype. if (prototype === null || @@ -122,7 +128,7 @@ function isRecord(value) { return false; } // If constructor does not have an Object-specific method. - // eslint-disable-next-line sonarjs/prefer-single-boolean-return, no-prototype-builtins + // eslint-disable-next-line sonar/prefer-single-boolean-return, no-prototype-builtins if (!prototype.hasOwnProperty("isPrototypeOf")) { return false; } @@ -137,7 +143,6 @@ function isRecord(value) { */ function mergeRecords$2(values, utils, meta) { const result = {}; - /* eslint-disable functional/no-loop-statements, functional/no-conditional-statements, functional/no-expression-statements, functional/immutable-data -- using imperative code here is more performant. */ for (const key of getKeys(values)) { const propValues = []; for (const value of values) { @@ -168,7 +173,6 @@ function mergeRecords$2(values, utils, meta) { result[key] = propertyResult; } } - /* eslint-enable functional/no-loop-statements, functional/no-conditional-statements, functional/no-expression-statements, functional/immutable-data */ return result; } /** @@ -196,19 +200,24 @@ function mergeMaps$2(values) { return new Map(getIterableOfIterables(values)); } /** - * Get the last value in the given array. + * Get the last non-undefined value in the given array. */ function mergeOthers$2(values) { - return values.at(-1); + for (let i = values.length - 1; i >= 0; i--) { + if (values[i] !== undefined) { + return values[i]; + } + } + return undefined; } var defaultMergeFunctions = /*#__PURE__*/Object.freeze({ - __proto__: null, - mergeArrays: mergeArrays$2, - mergeMaps: mergeMaps$2, - mergeOthers: mergeOthers$2, - mergeRecords: mergeRecords$2, - mergeSets: mergeSets$2 + __proto__: null, + mergeArrays: mergeArrays$2, + mergeMaps: mergeMaps$2, + mergeOthers: mergeOthers$2, + mergeRecords: mergeRecords$2, + mergeSets: mergeSets$2 }); /** @@ -216,9 +225,7 @@ var defaultMergeFunctions = /*#__PURE__*/Object.freeze({ * * @param objects - The objects to merge. */ -function deepmerge( -// eslint-disable-next-line functional/functional-parameters -...objects) { +function deepmerge(...objects) { return deepmergeCustom({})(...objects); } function deepmergeCustom(options, rootMetaData) { @@ -226,9 +233,7 @@ function deepmergeCustom(options, rootMetaData) { /** * The customized deepmerge function. */ - function customizedDeepmerge( - // eslint-disable-next-line functional/functional-parameters - ...objects) { + function customizedDeepmerge(...objects) { return mergeUnknowns(objects, utils, rootMetaData); } return customizedDeepmerge; @@ -269,7 +274,6 @@ function mergeUnknowns(values, utils, meta) { return mergeOthers$1(values, utils, meta); } const type = getObjectType(values[0]); - /* eslint-disable functional/no-loop-statements, functional/no-conditional-statements -- using imperative code here is more performant. */ 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) { @@ -278,7 +282,6 @@ function mergeUnknowns(values, utils, meta) { return mergeOthers$1(values, utils, meta); } } - /* eslint-enable functional/no-loop-statements, functional/no-conditional-statements */ switch (type) { case 1 /* ObjectType.RECORD */: { return mergeRecords$1(values, utils, meta); @@ -444,19 +447,25 @@ function mergeMaps(m_target, values) { } } /** - * Set the target to the last value. + * Set the target to the last non-undefined value. */ function mergeOthers(m_target, values) { - m_target.value = values.at(-1); + for (let i = values.length - 1; i >= 0; i--) { + if (values[i] !== undefined) { + m_target.value = values[i]; + return; + } + } + m_target.value = undefined; } var defaultMergeIntoFunctions = /*#__PURE__*/Object.freeze({ - __proto__: null, - mergeArrays: mergeArrays, - mergeMaps: mergeMaps, - mergeOthers: mergeOthers, - mergeRecords: mergeRecords, - mergeSets: mergeSets + __proto__: null, + mergeArrays: mergeArrays, + mergeMaps: mergeMaps, + mergeOthers: mergeOthers, + mergeRecords: mergeRecords, + mergeSets: mergeSets }); function deepmergeInto(target, ...objects) { @@ -500,9 +509,7 @@ function getIntoUtils(options, customizedDeepmergeInto) { * @param m_target - The target to merge into. * @param values - The values. */ -function mergeUnknownsInto(m_target, values, utils, meta -// eslint-disable-next-line @typescript-eslint/no-invalid-void-type -) { +function mergeUnknownsInto(m_target, values, utils, meta) { if (values.length === 0) { return; } diff --git a/dist/node/types/current/index.d.cts b/dist/node/index.d.cts similarity index 58% rename from dist/node/types/current/index.d.cts rename to dist/node/index.d.cts index 70985a14..65b554a8 100644 --- a/dist/node/types/current/index.d.cts +++ b/dist/node/index.d.cts @@ -1,24 +1,60 @@ /** - * Flatten a complex type such as a union or intersection of objects into a + * Simplify a complex type such as a union or intersection of objects into a * single object. */ -type FlatternAlias = Is extends true ? T : { - [P in keyof T]: T[P]; +type SimplifyObject = { + [K in keyof T]: T[K]; } & {}; /** - * Get the value of the given key in the given object. + * Flatten a collection of tuples of tuples into a collection of tuples. */ -type ValueOfKey, K extends PropertyKey> = K extends keyof T ? T[K] : never; +type FlattenTuples = { + [I in keyof T]: FlattenTuple; +}; +/** + * Flatten a tuple of tuples into a single tuple. + */ +type FlattenTuple = T extends readonly [ +] ? [ +] : T extends readonly [ + infer T0 +] ? [ + ...FlattenTuple +] : T extends readonly [ + infer T0, + ...infer Ts +] ? [ + ...FlattenTuple, + ...FlattenTuple +] : [ + T +]; /** * Safely test whether or not the first given types extends the second. * * Needed in particular for testing if a type is "never". */ -type Is = [T1] extends [T2] ? true : false; +type Is = [ + T1 +] extends [ + T2 +] ? true : false; /** * Safely test whether or not the given type is "never". */ 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. + */ +type Not = T extends true ? false : true; /** * Returns whether or not the given type a record. */ @@ -26,7 +62,10 @@ type IsRecord = And>, T extends Readonly> = Ts extends readonly [infer Head, ...infer Rest] ? IsRecord extends true ? Rest extends ReadonlyArray ? EveryIsRecord : true : false : true; +type EveryIsRecord> = Ts extends readonly [ + infer Head, + ...infer Rest +] ? IsRecord extends true ? Rest extends ReadonlyArray ? EveryIsRecord : true : false : true; /** * Returns whether or not the given type is an array. */ @@ -34,7 +73,15 @@ type IsArray = And>, T extends ReadonlyArray ? true : /** * Returns whether or not all the given types are arrays. */ -type EveryIsArray> = Ts extends readonly [infer T1] ? IsArray : Ts extends readonly [infer Head, ...infer Rest] ? IsArray extends true ? Rest extends readonly [unknown, ...ReadonlyArray] ? EveryIsArray : false : false : false; +type EveryIsArray> = Ts extends readonly [ + infer T1 +] ? IsArray : Ts extends readonly [ + infer Head, + ...infer Rest +] ? IsArray extends true ? Rest extends readonly [ + unknown, + ...ReadonlyArray +] ? EveryIsArray : false : false : false; /** * Returns whether or not the given type is an set. * @@ -46,7 +93,15 @@ type IsSet = And>, T extends Readonly> ? * * Note: This may also return true if all are maps. */ -type EveryIsSet> = Ts extends Readonly ? IsSet : Ts extends readonly [infer Head, ...infer Rest] ? IsSet extends true ? Rest extends readonly [unknown, ...ReadonlyArray] ? EveryIsSet : false : false : false; +type EveryIsSet> = Ts extends Readonly ? IsSet : Ts extends readonly [ + infer Head, + ...infer Rest +] ? IsSet extends true ? Rest extends readonly [ + unknown, + ...ReadonlyArray +] ? EveryIsSet : false : false : false; /** * Returns whether or not the given type is an map. */ @@ -54,15 +109,15 @@ type IsMap = And>, T extends Readonly> = Ts extends Readonly ? IsMap : Ts extends readonly [infer Head, ...infer Rest] ? IsMap extends true ? Rest extends readonly [unknown, ...ReadonlyArray] ? EveryIsMap : false : false : false; -/** - * And operator for types. - */ -type And = T1 extends false ? false : T2; -/** - * Not operator for types. - */ -type Not = T extends true ? false : true; +type EveryIsMap> = Ts extends Readonly ? IsMap : Ts extends readonly [ + infer Head, + ...infer Rest +] ? IsMap extends true ? Rest extends readonly [ + unknown, + ...ReadonlyArray +] ? EveryIsMap : false : false : false; /** * Union of the sets' values' types */ @@ -70,7 +125,10 @@ type UnionSetValues> = UnionSetValuesHelper, Acc> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Readonly> ? Rest extends ReadonlyArray ? UnionSetValuesHelper : Acc | V1 : never : Acc; +type UnionSetValuesHelper, Acc> = Ts extends readonly [ + infer Head, + ...infer Rest +] ? Head extends Readonly> ? Rest extends ReadonlyArray ? UnionSetValuesHelper : Acc | V1 : never : Acc; /** * Union of the maps' values' types */ @@ -78,7 +136,11 @@ type UnionMapKeys> = UnionMapKeysHelper, Acc> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Readonly> ? Rest extends readonly [] ? Acc | K1 : UnionMapKeysHelper : never : Acc; +type UnionMapKeysHelper, Acc> = Ts extends readonly [ + infer Head, + ...infer Rest +] ? Head extends Readonly> ? Rest extends readonly [ +] ? Acc | K1 : UnionMapKeysHelper : never : Acc; /** * Union of the maps' keys' types */ @@ -86,53 +148,105 @@ type UnionMapValues> = UnionMapValuesHelper, Acc> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Readonly> ? Rest extends readonly [] ? Acc | V1 : UnionMapValuesHelper : never : Acc; -/** - * Get the keys of the type what match a certain criteria. - */ -type KeysOfType = { - [K in keyof T]: T[K] extends U ? K : never; -}[keyof T]; -/** - * Get the required keys of the type. - */ -type RequiredKeys = Exclude>, undefined>; -/** - * Get all the required keys on the types in the tuple. - */ -type RequiredKeysOf]> = RequiredKeysOfHelper; -/** - * Tail-recursive helper type for RequiredKeysOf. - */ -type RequiredKeysOfHelper], Acc> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Record ? Rest extends readonly [unknown, ...ReadonlyArray] ? RequiredKeysOfHelper> : Acc | RequiredKeys : never : Acc; -/** - * Get the optional keys of the type. - */ -type OptionalKeys = Exclude>; -/** - * Get all the optional keys on the types in the tuple. - */ -type OptionalKeysOf]> = OptionalKeysOfHelper; -/** - * Tail-recursive helper type for OptionalKeysOf. - */ -type OptionalKeysOfHelper], Acc> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Record ? Rest extends readonly [unknown, ...ReadonlyArray] ? OptionalKeysOfHelper> : Acc | OptionalKeys : never : Acc; +type UnionMapValuesHelper, Acc> = Ts extends readonly [ + infer Head, + ...infer Rest +] ? Head extends Readonly> ? Rest extends readonly [ +] ? Acc | V1 : UnionMapValuesHelper : never : Acc; /** * Filter out nevers from a tuple. */ -type FilterOutNever> = FilterOutNeverHelper; +type FilterOutNever = T extends ReadonlyArray ? FilterOutNeverHelper : never; /** * Tail-recursive helper type for FilterOutNever. */ -type FilterOutNeverHelper, Acc extends ReadonlyArray> = T extends readonly [] ? Acc : T extends readonly [infer Head, ...infer Rest] ? IsNever extends true ? FilterOutNeverHelper : FilterOutNeverHelper : T; +type FilterOutNeverHelper, Acc extends ReadonlyArray> = T extends readonly [ +] ? Acc : T extends readonly [ + infer Head, + ...infer Rest +] ? IsNever extends true ? FilterOutNeverHelper : FilterOutNeverHelper : T; /** * Is the type a tuple? */ -type IsTuple> = T extends readonly [] ? true : T extends readonly [unknown, ...ReadonlyArray] ? true : false; - +type IsTuple> = T extends readonly [ +] ? true : T extends readonly [ + unknown, + ...ReadonlyArray +] ? true : false; +/** + * Perfrom a transpose operation on a 2D tuple. + */ +type TransposeTuple = T extends readonly [ + ...(readonly [ + ...unknown[] + ]) +] ? T extends readonly [ +] ? [ +] : T extends readonly [ + infer X extends ReadonlyArray +] ? TransposeTupleSimpleCase : T extends readonly [ + infer X extends ReadonlyArray, + ...infer XS extends ReadonlyArray> +] ? PrependCol> : T : never; +type PrependCol, S extends ReadonlyArray>> = T extends readonly [ +] ? S extends readonly [ +] ? [ +] : never : T extends readonly [ + infer X, + ...infer XS +] ? S extends readonly [ + readonly [ + ...infer Y + ], + ...infer YS extends ReadonlyArray> +] ? [ + [ + X, + ...Y + ], + ...PrependCol +] : never : never; +type TransposeTupleSimpleCase = T extends readonly [ +] ? [ +] : T extends readonly [ + infer X, + ...infer XS +] ? [ + [ + X + ], + ...TransposeTupleSimpleCase +] : never; +/** + * Convert a tuple to an intersection of each of its types. + */ +type TupleToIntersection> = { + [K in keyof T]: (x: T[K]) => void; +} extends Record void> ? I : never; +/** + * Convert a union to a tuple. + * + * Warning: The order of the elements is non-deterministic. + * Warning 2: The union maybe me modified by the TypeScript engine before convertion. + * Warning 3: This implementation relies on a hack/limitation in TypeScript. + */ +type TuplifyUnion> = IsNever extends true ? [ +] : [ + ...TuplifyUnion>, + L +]; +type UnionToIntersection = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; +type LastOf = UnionToIntersection T : never> extends () => infer R ? R : never; /** * 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> { readonly DeepMergeLeafURI: DeepMergeLeaf; readonly DeepMergeRecordsDefaultURI: DeepMergeRecordsDefaultHKT; @@ -176,7 +290,10 @@ type DeepMergeMergeFunctionsURIs = Readonly<{ /** * Deep merge types. */ -type DeepMergeHKT, MF extends DeepMergeMergeFunctionsURIs, 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 : unknown; +type DeepMergeHKT, MF extends DeepMergeMergeFunctionsURIs, 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 : unknown; /** * Deep merge records. */ @@ -201,16 +318,16 @@ type DeepMergeOthersHKT, MF extends DeepMergeM * The merge function that returns a leaf. */ type DeepMergeLeafURI = "DeepMergeLeafURI"; -/** - * Get the leaf type from many types that can't be merged. - * - * @deprecated Use `DeepMergeLeaf` instead. - */ -type DeepMergeLeafHKT> = DeepMergeLeaf; /** * Get the leaf type from many types that can't be merged. */ -type DeepMergeLeaf> = Ts extends readonly [] ? never : Ts extends readonly [infer T] ? T : Ts extends readonly [...infer Rest, infer Tail] ? IsNever extends true ? Rest extends ReadonlyArray ? DeepMergeLeaf : never : Tail : never; +type DeepMergeLeaf> = Ts extends readonly [ +] ? never : Ts extends readonly [ + infer T +] ? T : Ts extends readonly [ + ...infer Rest, + infer Tail +] ? Or, Is> extends true ? Rest extends ReadonlyArray ? DeepMergeLeaf : never : Tail : never; /** * The meta data deepmerge is able to provide. */ @@ -218,7 +335,6 @@ type DeepMergeBuiltInMetaData = Readonly<{ key: PropertyKey; parents: ReadonlyArray>>; }>; - /** * The default merge function to merge records with. */ @@ -245,41 +361,152 @@ type DeepMergeMergeFunctionsDefaultURIs = Readonly<{ DeepMergeMapsURI: DeepMergeMapsDefaultURI; DeepMergeOthersURI: DeepMergeLeafURI; }>; -/** - * A union of all the props that should not be included in type information for - * merged records. - */ -type BlacklistedRecordProps = "__proto__"; +type RecordEntries> = TuplifyUnion<{ + [K in keyof T]: [ + K, + T[K] + ]; +}[keyof T]>; +type RecordMeta = Record; +type RecordPropertyMeta = { + key: Key; + value: Value; + optional: Optional; +}; +type RecordsToRecordMeta>> = { + [I in keyof Ts]: RecordToRecordMeta; +}; +type RecordToRecordMeta> = { + [K in keyof T]-?: { + key: K; + value: Required[K]; + optional: {} extends Pick ? true : false; + }; +}; /** * Deep merge records. */ -type DeepMergeRecordsDefaultHKT, MF extends DeepMergeMergeFunctionsURIs, M> = Ts extends Readonly>]> ? FlatternAlias, BlacklistedRecordProps>> : {}; +type DeepMergeRecordsDefaultHKT, MF extends DeepMergeMergeFunctionsURIs, M> = Ts extends ReadonlyArray> ? SimplifyObject, MF, M>> : never; /** * Deep merge record props. */ -type DeepMergeRecordsDefaultHKTInternalProps], MF extends DeepMergeMergeFunctionsURIs, M> = { - [K in OptionalKeysOf]?: DeepMergeHKT, MF, M>; -} & { - [K in RequiredKeysOf]: DeepMergeHKT, MF, M>; +type DeepMergeRecordMetaDefaultHKTProps, MF extends DeepMergeMergeFunctionsURIs, M> = CreateRecordFromMeta, MF, M>; +type MergeRecordMeta> = GroupValuesByKey>; +}>>>; +type GroupValuesByKey = Ts extends readonly [ + infer Keys extends ReadonlyArray, + infer Values +] ? { + [I in keyof Keys]: DeepMergeRecordPropertyMetaDefaultHKTGetPossible>; +} : never; +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; +}> : never; +type CreateRecordForKeyFromMeta, Optional extends boolean, MF extends DeepMergeMergeFunctionsURIs, M> = Optional extends true ? { + [k in Key]+?: DeepMergeHKT; +} : { + [k in Key]-?: DeepMergeHKT; }; /** - * Get the value of the property. + * Get the possible types of a property. */ -type DeepMergeRecordsDefaultHKTInternalPropValue], K extends PropertyKey, M> = FilterOutNever>; +type DeepMergeRecordPropertyMetaDefaultHKTGetPossible = Ts extends readonly [ + RecordPropertyMeta, + ...ReadonlyArray +] ? DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper : never; /** - * Tail-recursive helper type for DeepMergeRecordsDefaultHKTInternalPropValue. + * Tail-recursive helper type for DeepMergeRecordPropertyMetaDefaultHKTGetPossible. */ -type DeepMergeRecordsDefaultHKTInternalPropValueHelper], K extends PropertyKey, M, Acc extends ReadonlyArray> = Ts extends readonly [ - infer Head extends Readonly>, - ...infer Rest -] ? Rest extends readonly [unknown, ...ReadonlyArray] ? DeepMergeRecordsDefaultHKTInternalPropValueHelper -]> : [...Acc, ValueOfKey] : never; +type DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper +], Acc extends { + key: PropertyKey; + values: ReadonlyArray; + optional: boolean; +}> = Ts extends [ + ...infer Rest, + { + key: infer K extends PropertyKey; + value: infer V; + optional: infer O extends boolean; + } +] ? Acc["optional"] extends true ? Acc extends { + values: [ + infer Head, + ...infer AccRest + ]; +} ? Rest extends readonly [ + RecordPropertyMeta, + ...ReadonlyArray +] ? DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper : { + key: K; + values: [ + V | Head, + ...AccRest + ]; + optional: O; +} : Rest extends readonly [ + RecordPropertyMeta, + ...ReadonlyArray +] ? DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper : { + key: K; + values: [ + V, + ...Acc["values"] + ]; + optional: O; +} : Rest extends readonly [ + RecordPropertyMeta, + ...ReadonlyArray +] ? DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper : { + key: K; + values: [ + V, + ...Acc["values"] + ]; + optional: O; +} : never; /** - * Deep merge 2 arrays. + * Deep merge arrays. */ -type DeepMergeArraysDefaultHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeArraysDefaultHKTHelper; +type DeepMergeArraysDefaultHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeArraysDefaultHKTHelper; /** * Tail-recursive helper type for DeepMergeArraysDefaultHKT. */ @@ -289,35 +516,45 @@ type DeepMergeArraysDefaultHKTHelper, MF exten ] ? Rest extends readonly [ ReadonlyArray, ...ReadonlyArray> -] ? DeepMergeArraysDefaultHKTHelper : [...Acc, ...Head] : never; +] ? DeepMergeArraysDefaultHKTHelper : [ + ...Acc, + ...Head +] : never; /** - * Deep merge 2 sets. + * Deep merge sets. */ type DeepMergeSetsDefaultHKT> = Set>; /** - * Deep merge 2 maps. + * Deep merge maps. */ type DeepMergeMapsDefaultHKT> = Map, UnionMapValues>; /** * Get the merge functions with defaults apply from the given subset. */ type GetDeepMergeMergeFunctionsURIs> = Readonly<{ + // prettier-ignore DeepMergeRecordsURI: PMF["DeepMergeRecordsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeRecordsURI"] : DeepMergeRecordsDefaultURI; + // prettier-ignore DeepMergeArraysURI: PMF["DeepMergeArraysURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeArraysURI"] : DeepMergeArraysDefaultURI; + // prettier-ignore DeepMergeSetsURI: PMF["DeepMergeSetsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeSetsURI"] : DeepMergeSetsDefaultURI; + // prettier-ignore DeepMergeMapsURI: PMF["DeepMergeMapsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeMapsURI"] : DeepMergeMapsDefaultURI; + // prettier-ignore DeepMergeOthersURI: PMF["DeepMergeOthersURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeOthersURI"] : DeepMergeLeafURI; }>; - /** * The default merge functions. */ -type MergeFunctions$1 = { - mergeRecords: typeof mergeRecords$1; - mergeArrays: typeof mergeArrays$1; - mergeSets: typeof mergeSets$1; - mergeMaps: typeof mergeMaps$1; - mergeOthers: typeof mergeOthers$1; +type MergeFunctions = { + mergeRecords: typeof mergeRecords; + mergeArrays: typeof mergeArrays; + mergeSets: typeof mergeSets; + mergeMaps: typeof mergeMaps; + mergeOthers: typeof mergeOthers; }; /** * The default strategy to merge records into a target record. @@ -325,72 +562,43 @@ type MergeFunctions$1 = { * @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$1>, U extends DeepMergeMergeIntoFunctionUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined): void; +declare function mergeRecords>, U extends DeepMergeMergeIntoFunctionUtils, 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. * * @param m_target - The result will be mutated into this array * @param values - The arrays (including the target's value if there is one). */ -declare function mergeArrays$1>>(m_target: Reference, values: Ts): void; +declare function mergeArrays>>(m_target: Reference, values: Ts): void; /** * The default strategy to merge sets into a target set. * * @param m_target - The result will be mutated into this set * @param values - The sets (including the target's value if there is one). */ -declare function mergeSets$1>>>(m_target: Reference>, values: Ts): void; +declare function mergeSets>>>(m_target: Reference>, values: Ts): void; /** * The default strategy to merge maps into a target map. * * @param m_target - The result will be mutated into this map * @param values - The maps (including the target's value if there is one). */ -declare function mergeMaps$1>>>(m_target: Reference>, values: Ts): void; +declare function mergeMaps>>>(m_target: Reference>, values: Ts): void; /** - * Set the target to the last value. + * Set the target to the last non-undefined value. */ -declare function mergeOthers$1>(m_target: Reference, values: Ts): void; - +declare function mergeOthers>(m_target: Reference, values: Ts): void; +type MergeIntoFunctions = MergeFunctions; /** * The default merge functions. */ -type MergeFunctions = { +type MergeFunctions$0 = { mergeRecords: typeof mergeRecords; mergeArrays: typeof mergeArrays; mergeSets: typeof mergeSets; mergeMaps: typeof mergeMaps; mergeOthers: typeof mergeOthers; }; -/** - * The default strategy to merge records. - * - * @param values - The records. - */ -declare function mergeRecords>, U extends DeepMergeMergeFunctionUtils, MF extends DeepMergeMergeFunctionsURIs, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData>(values: Ts, utils: U, meta: M | undefined): DeepMergeRecordsDefaultHKT; -/** - * The default strategy to merge arrays. - * - * @param values - The arrays. - */ -declare function mergeArrays>, MF extends DeepMergeMergeFunctionsURIs, M>(values: Ts): DeepMergeArraysDefaultHKT; -/** - * The default strategy to merge sets. - * - * @param values - The sets. - */ -declare function mergeSets>>>(values: Ts): DeepMergeSetsDefaultHKT; -/** - * The default strategy to merge maps. - * - * @param values - The maps. - */ -declare function mergeMaps>>>(values: Ts): DeepMergeMapsDefaultHKT; -/** - * Get the last value in the given array. - */ -declare function mergeOthers>(values: Ts): unknown; - /** * The options the user can pass to customize deepmerge. */ @@ -439,6 +647,7 @@ type DeepMergeMergeFunctions>>, U extends DeepMergeMergeFunctionUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; mergeOthers: , U extends DeepMergeMergeFunctionUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; }>; +// eslint-disable-next-line ts/no-invalid-void-type type DeepMergeMergeIntoFunctionsReturnType = void | symbol; /** * All the merge functions that deepmerge uses. @@ -455,7 +664,7 @@ type DeepMergeMergeIntoFunctions = Readonly<{ mergeFunctions: DeepMergeMergeFunctions; - defaultMergeFunctions: MergeFunctions; + defaultMergeFunctions: MergeFunctions$0; metaDataUpdater: MetaDataUpdater; deepmerge: >(...values: Ts) => unknown; useImplicitDefaultMerging: boolean; @@ -469,34 +678,34 @@ type DeepMergeMergeFunctionUtils = Readonly<{ mergeFunctions: DeepMergeMergeIntoFunctions; - defaultMergeFunctions: MergeFunctions$1; + defaultMergeFunctions: MergeIntoFunctions; metaDataUpdater: MetaDataUpdater; deepmergeInto: >(target: Target, ...values: Ts) => void; actions: Readonly<{ defaultMerge: symbol; }>; }>; - /** * Deeply merge objects. * * @param objects - The objects to merge. */ -declare function deepmerge>>(...objects: readonly [...Ts]): DeepMergeHKT; +declare function deepmerge>>(...objects: readonly [ + ...Ts +]): 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, 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. * @@ -510,7 +719,7 @@ declare function deepmergeInto(target: T, ...objects: Readonly * @param target - This object will be mutated with the merge result. * @param objects - The objects to merge into the target. */ -declare function deepmergeInto>(target: Target, ...objects: Ts): asserts target is FlatternAlias>(target: Target, ...objects: Ts): asserts target is SimplifyObject>; @@ -519,15 +728,14 @@ declare function deepmergeInto): >(target: Target, ...objects: Ts) => void; +declare function deepmergeIntoCustom(options: DeepMergeIntoOptions): >(target: Target, ...objects: Ts) => void; /** * 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 deepmergeIntoCustom(options: DeepMergeIntoOptions, rootMetaData?: MetaData): >(target: Target, ...objects: Ts) => void; - +declare function deepmergeIntoCustom(options: DeepMergeIntoOptions, rootMetaData?: MetaData): >(target: Target, ...objects: Ts) => void; /** * The different types of objects deepmerge-ts support. */ @@ -563,5 +771,5 @@ declare function getKeys(objects: ReadonlyArray): Set; * @returns Whether the object has the property. */ declare function objectHasProperty(object: object, property: PropertyKey): boolean; - -export { DeepMergeArraysDefaultHKT, DeepMergeBuiltInMetaData, DeepMergeHKT, DeepMergeIntoOptions, DeepMergeLeaf, DeepMergeLeafHKT, DeepMergeLeafURI, DeepMergeMapsDefaultHKT, DeepMergeMergeFunctionURItoKind, DeepMergeMergeFunctionUtils, DeepMergeMergeFunctionsDefaultURIs, MergeFunctions as DeepMergeMergeFunctionsDefaults, DeepMergeMergeFunctionsURIs, DeepMergeMergeIntoFunctionUtils, MergeFunctions$1 as DeepMergeMergeIntoFunctionsDefaults, DeepMergeOptions, DeepMergeRecordsDefaultHKT, DeepMergeSetsDefaultHKT, Reference as DeepMergeValueReference, GetDeepMergeMergeFunctionsURIs, ObjectType, deepmerge, deepmergeCustom, deepmergeInto, deepmergeIntoCustom, getKeys, getObjectType, objectHasProperty }; +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 }; diff --git a/dist/node/types/current/index.d.mts b/dist/node/index.d.mts similarity index 58% rename from dist/node/types/current/index.d.mts rename to dist/node/index.d.mts index 70985a14..65b554a8 100644 --- a/dist/node/types/current/index.d.mts +++ b/dist/node/index.d.mts @@ -1,24 +1,60 @@ /** - * Flatten a complex type such as a union or intersection of objects into a + * Simplify a complex type such as a union or intersection of objects into a * single object. */ -type FlatternAlias = Is extends true ? T : { - [P in keyof T]: T[P]; +type SimplifyObject = { + [K in keyof T]: T[K]; } & {}; /** - * Get the value of the given key in the given object. + * Flatten a collection of tuples of tuples into a collection of tuples. */ -type ValueOfKey, K extends PropertyKey> = K extends keyof T ? T[K] : never; +type FlattenTuples = { + [I in keyof T]: FlattenTuple; +}; +/** + * Flatten a tuple of tuples into a single tuple. + */ +type FlattenTuple = T extends readonly [ +] ? [ +] : T extends readonly [ + infer T0 +] ? [ + ...FlattenTuple +] : T extends readonly [ + infer T0, + ...infer Ts +] ? [ + ...FlattenTuple, + ...FlattenTuple +] : [ + T +]; /** * Safely test whether or not the first given types extends the second. * * Needed in particular for testing if a type is "never". */ -type Is = [T1] extends [T2] ? true : false; +type Is = [ + T1 +] extends [ + T2 +] ? true : false; /** * Safely test whether or not the given type is "never". */ 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. + */ +type Not = T extends true ? false : true; /** * Returns whether or not the given type a record. */ @@ -26,7 +62,10 @@ type IsRecord = And>, T extends Readonly> = Ts extends readonly [infer Head, ...infer Rest] ? IsRecord extends true ? Rest extends ReadonlyArray ? EveryIsRecord : true : false : true; +type EveryIsRecord> = Ts extends readonly [ + infer Head, + ...infer Rest +] ? IsRecord extends true ? Rest extends ReadonlyArray ? EveryIsRecord : true : false : true; /** * Returns whether or not the given type is an array. */ @@ -34,7 +73,15 @@ type IsArray = And>, T extends ReadonlyArray ? true : /** * Returns whether or not all the given types are arrays. */ -type EveryIsArray> = Ts extends readonly [infer T1] ? IsArray : Ts extends readonly [infer Head, ...infer Rest] ? IsArray extends true ? Rest extends readonly [unknown, ...ReadonlyArray] ? EveryIsArray : false : false : false; +type EveryIsArray> = Ts extends readonly [ + infer T1 +] ? IsArray : Ts extends readonly [ + infer Head, + ...infer Rest +] ? IsArray extends true ? Rest extends readonly [ + unknown, + ...ReadonlyArray +] ? EveryIsArray : false : false : false; /** * Returns whether or not the given type is an set. * @@ -46,7 +93,15 @@ type IsSet = And>, T extends Readonly> ? * * Note: This may also return true if all are maps. */ -type EveryIsSet> = Ts extends Readonly ? IsSet : Ts extends readonly [infer Head, ...infer Rest] ? IsSet extends true ? Rest extends readonly [unknown, ...ReadonlyArray] ? EveryIsSet : false : false : false; +type EveryIsSet> = Ts extends Readonly ? IsSet : Ts extends readonly [ + infer Head, + ...infer Rest +] ? IsSet extends true ? Rest extends readonly [ + unknown, + ...ReadonlyArray +] ? EveryIsSet : false : false : false; /** * Returns whether or not the given type is an map. */ @@ -54,15 +109,15 @@ type IsMap = And>, T extends Readonly> = Ts extends Readonly ? IsMap : Ts extends readonly [infer Head, ...infer Rest] ? IsMap extends true ? Rest extends readonly [unknown, ...ReadonlyArray] ? EveryIsMap : false : false : false; -/** - * And operator for types. - */ -type And = T1 extends false ? false : T2; -/** - * Not operator for types. - */ -type Not = T extends true ? false : true; +type EveryIsMap> = Ts extends Readonly ? IsMap : Ts extends readonly [ + infer Head, + ...infer Rest +] ? IsMap extends true ? Rest extends readonly [ + unknown, + ...ReadonlyArray +] ? EveryIsMap : false : false : false; /** * Union of the sets' values' types */ @@ -70,7 +125,10 @@ type UnionSetValues> = UnionSetValuesHelper, Acc> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Readonly> ? Rest extends ReadonlyArray ? UnionSetValuesHelper : Acc | V1 : never : Acc; +type UnionSetValuesHelper, Acc> = Ts extends readonly [ + infer Head, + ...infer Rest +] ? Head extends Readonly> ? Rest extends ReadonlyArray ? UnionSetValuesHelper : Acc | V1 : never : Acc; /** * Union of the maps' values' types */ @@ -78,7 +136,11 @@ type UnionMapKeys> = UnionMapKeysHelper, Acc> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Readonly> ? Rest extends readonly [] ? Acc | K1 : UnionMapKeysHelper : never : Acc; +type UnionMapKeysHelper, Acc> = Ts extends readonly [ + infer Head, + ...infer Rest +] ? Head extends Readonly> ? Rest extends readonly [ +] ? Acc | K1 : UnionMapKeysHelper : never : Acc; /** * Union of the maps' keys' types */ @@ -86,53 +148,105 @@ type UnionMapValues> = UnionMapValuesHelper, Acc> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Readonly> ? Rest extends readonly [] ? Acc | V1 : UnionMapValuesHelper : never : Acc; -/** - * Get the keys of the type what match a certain criteria. - */ -type KeysOfType = { - [K in keyof T]: T[K] extends U ? K : never; -}[keyof T]; -/** - * Get the required keys of the type. - */ -type RequiredKeys = Exclude>, undefined>; -/** - * Get all the required keys on the types in the tuple. - */ -type RequiredKeysOf]> = RequiredKeysOfHelper; -/** - * Tail-recursive helper type for RequiredKeysOf. - */ -type RequiredKeysOfHelper], Acc> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Record ? Rest extends readonly [unknown, ...ReadonlyArray] ? RequiredKeysOfHelper> : Acc | RequiredKeys : never : Acc; -/** - * Get the optional keys of the type. - */ -type OptionalKeys = Exclude>; -/** - * Get all the optional keys on the types in the tuple. - */ -type OptionalKeysOf]> = OptionalKeysOfHelper; -/** - * Tail-recursive helper type for OptionalKeysOf. - */ -type OptionalKeysOfHelper], Acc> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Record ? Rest extends readonly [unknown, ...ReadonlyArray] ? OptionalKeysOfHelper> : Acc | OptionalKeys : never : Acc; +type UnionMapValuesHelper, Acc> = Ts extends readonly [ + infer Head, + ...infer Rest +] ? Head extends Readonly> ? Rest extends readonly [ +] ? Acc | V1 : UnionMapValuesHelper : never : Acc; /** * Filter out nevers from a tuple. */ -type FilterOutNever> = FilterOutNeverHelper; +type FilterOutNever = T extends ReadonlyArray ? FilterOutNeverHelper : never; /** * Tail-recursive helper type for FilterOutNever. */ -type FilterOutNeverHelper, Acc extends ReadonlyArray> = T extends readonly [] ? Acc : T extends readonly [infer Head, ...infer Rest] ? IsNever extends true ? FilterOutNeverHelper : FilterOutNeverHelper : T; +type FilterOutNeverHelper, Acc extends ReadonlyArray> = T extends readonly [ +] ? Acc : T extends readonly [ + infer Head, + ...infer Rest +] ? IsNever extends true ? FilterOutNeverHelper : FilterOutNeverHelper : T; /** * Is the type a tuple? */ -type IsTuple> = T extends readonly [] ? true : T extends readonly [unknown, ...ReadonlyArray] ? true : false; - +type IsTuple> = T extends readonly [ +] ? true : T extends readonly [ + unknown, + ...ReadonlyArray +] ? true : false; +/** + * Perfrom a transpose operation on a 2D tuple. + */ +type TransposeTuple = T extends readonly [ + ...(readonly [ + ...unknown[] + ]) +] ? T extends readonly [ +] ? [ +] : T extends readonly [ + infer X extends ReadonlyArray +] ? TransposeTupleSimpleCase : T extends readonly [ + infer X extends ReadonlyArray, + ...infer XS extends ReadonlyArray> +] ? PrependCol> : T : never; +type PrependCol, S extends ReadonlyArray>> = T extends readonly [ +] ? S extends readonly [ +] ? [ +] : never : T extends readonly [ + infer X, + ...infer XS +] ? S extends readonly [ + readonly [ + ...infer Y + ], + ...infer YS extends ReadonlyArray> +] ? [ + [ + X, + ...Y + ], + ...PrependCol +] : never : never; +type TransposeTupleSimpleCase = T extends readonly [ +] ? [ +] : T extends readonly [ + infer X, + ...infer XS +] ? [ + [ + X + ], + ...TransposeTupleSimpleCase +] : never; +/** + * Convert a tuple to an intersection of each of its types. + */ +type TupleToIntersection> = { + [K in keyof T]: (x: T[K]) => void; +} extends Record void> ? I : never; +/** + * Convert a union to a tuple. + * + * Warning: The order of the elements is non-deterministic. + * Warning 2: The union maybe me modified by the TypeScript engine before convertion. + * Warning 3: This implementation relies on a hack/limitation in TypeScript. + */ +type TuplifyUnion> = IsNever extends true ? [ +] : [ + ...TuplifyUnion>, + L +]; +type UnionToIntersection = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never; +type LastOf = UnionToIntersection T : never> extends () => infer R ? R : never; /** * 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> { readonly DeepMergeLeafURI: DeepMergeLeaf; readonly DeepMergeRecordsDefaultURI: DeepMergeRecordsDefaultHKT; @@ -176,7 +290,10 @@ type DeepMergeMergeFunctionsURIs = Readonly<{ /** * Deep merge types. */ -type DeepMergeHKT, MF extends DeepMergeMergeFunctionsURIs, 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 : unknown; +type DeepMergeHKT, MF extends DeepMergeMergeFunctionsURIs, 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 : unknown; /** * Deep merge records. */ @@ -201,16 +318,16 @@ type DeepMergeOthersHKT, MF extends DeepMergeM * The merge function that returns a leaf. */ type DeepMergeLeafURI = "DeepMergeLeafURI"; -/** - * Get the leaf type from many types that can't be merged. - * - * @deprecated Use `DeepMergeLeaf` instead. - */ -type DeepMergeLeafHKT> = DeepMergeLeaf; /** * Get the leaf type from many types that can't be merged. */ -type DeepMergeLeaf> = Ts extends readonly [] ? never : Ts extends readonly [infer T] ? T : Ts extends readonly [...infer Rest, infer Tail] ? IsNever extends true ? Rest extends ReadonlyArray ? DeepMergeLeaf : never : Tail : never; +type DeepMergeLeaf> = Ts extends readonly [ +] ? never : Ts extends readonly [ + infer T +] ? T : Ts extends readonly [ + ...infer Rest, + infer Tail +] ? Or, Is> extends true ? Rest extends ReadonlyArray ? DeepMergeLeaf : never : Tail : never; /** * The meta data deepmerge is able to provide. */ @@ -218,7 +335,6 @@ type DeepMergeBuiltInMetaData = Readonly<{ key: PropertyKey; parents: ReadonlyArray>>; }>; - /** * The default merge function to merge records with. */ @@ -245,41 +361,152 @@ type DeepMergeMergeFunctionsDefaultURIs = Readonly<{ DeepMergeMapsURI: DeepMergeMapsDefaultURI; DeepMergeOthersURI: DeepMergeLeafURI; }>; -/** - * A union of all the props that should not be included in type information for - * merged records. - */ -type BlacklistedRecordProps = "__proto__"; +type RecordEntries> = TuplifyUnion<{ + [K in keyof T]: [ + K, + T[K] + ]; +}[keyof T]>; +type RecordMeta = Record; +type RecordPropertyMeta = { + key: Key; + value: Value; + optional: Optional; +}; +type RecordsToRecordMeta>> = { + [I in keyof Ts]: RecordToRecordMeta; +}; +type RecordToRecordMeta> = { + [K in keyof T]-?: { + key: K; + value: Required[K]; + optional: {} extends Pick ? true : false; + }; +}; /** * Deep merge records. */ -type DeepMergeRecordsDefaultHKT, MF extends DeepMergeMergeFunctionsURIs, M> = Ts extends Readonly>]> ? FlatternAlias, BlacklistedRecordProps>> : {}; +type DeepMergeRecordsDefaultHKT, MF extends DeepMergeMergeFunctionsURIs, M> = Ts extends ReadonlyArray> ? SimplifyObject, MF, M>> : never; /** * Deep merge record props. */ -type DeepMergeRecordsDefaultHKTInternalProps], MF extends DeepMergeMergeFunctionsURIs, M> = { - [K in OptionalKeysOf]?: DeepMergeHKT, MF, M>; -} & { - [K in RequiredKeysOf]: DeepMergeHKT, MF, M>; +type DeepMergeRecordMetaDefaultHKTProps, MF extends DeepMergeMergeFunctionsURIs, M> = CreateRecordFromMeta, MF, M>; +type MergeRecordMeta> = GroupValuesByKey>; +}>>>; +type GroupValuesByKey = Ts extends readonly [ + infer Keys extends ReadonlyArray, + infer Values +] ? { + [I in keyof Keys]: DeepMergeRecordPropertyMetaDefaultHKTGetPossible>; +} : never; +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; +}> : never; +type CreateRecordForKeyFromMeta, Optional extends boolean, MF extends DeepMergeMergeFunctionsURIs, M> = Optional extends true ? { + [k in Key]+?: DeepMergeHKT; +} : { + [k in Key]-?: DeepMergeHKT; }; /** - * Get the value of the property. + * Get the possible types of a property. */ -type DeepMergeRecordsDefaultHKTInternalPropValue], K extends PropertyKey, M> = FilterOutNever>; +type DeepMergeRecordPropertyMetaDefaultHKTGetPossible = Ts extends readonly [ + RecordPropertyMeta, + ...ReadonlyArray +] ? DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper : never; /** - * Tail-recursive helper type for DeepMergeRecordsDefaultHKTInternalPropValue. + * Tail-recursive helper type for DeepMergeRecordPropertyMetaDefaultHKTGetPossible. */ -type DeepMergeRecordsDefaultHKTInternalPropValueHelper], K extends PropertyKey, M, Acc extends ReadonlyArray> = Ts extends readonly [ - infer Head extends Readonly>, - ...infer Rest -] ? Rest extends readonly [unknown, ...ReadonlyArray] ? DeepMergeRecordsDefaultHKTInternalPropValueHelper -]> : [...Acc, ValueOfKey] : never; +type DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper +], Acc extends { + key: PropertyKey; + values: ReadonlyArray; + optional: boolean; +}> = Ts extends [ + ...infer Rest, + { + key: infer K extends PropertyKey; + value: infer V; + optional: infer O extends boolean; + } +] ? Acc["optional"] extends true ? Acc extends { + values: [ + infer Head, + ...infer AccRest + ]; +} ? Rest extends readonly [ + RecordPropertyMeta, + ...ReadonlyArray +] ? DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper : { + key: K; + values: [ + V | Head, + ...AccRest + ]; + optional: O; +} : Rest extends readonly [ + RecordPropertyMeta, + ...ReadonlyArray +] ? DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper : { + key: K; + values: [ + V, + ...Acc["values"] + ]; + optional: O; +} : Rest extends readonly [ + RecordPropertyMeta, + ...ReadonlyArray +] ? DeepMergeRecordPropertyMetaDefaultHKTGetPossibleHelper : { + key: K; + values: [ + V, + ...Acc["values"] + ]; + optional: O; +} : never; /** - * Deep merge 2 arrays. + * Deep merge arrays. */ -type DeepMergeArraysDefaultHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeArraysDefaultHKTHelper; +type DeepMergeArraysDefaultHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeArraysDefaultHKTHelper; /** * Tail-recursive helper type for DeepMergeArraysDefaultHKT. */ @@ -289,35 +516,45 @@ type DeepMergeArraysDefaultHKTHelper, MF exten ] ? Rest extends readonly [ ReadonlyArray, ...ReadonlyArray> -] ? DeepMergeArraysDefaultHKTHelper : [...Acc, ...Head] : never; +] ? DeepMergeArraysDefaultHKTHelper : [ + ...Acc, + ...Head +] : never; /** - * Deep merge 2 sets. + * Deep merge sets. */ type DeepMergeSetsDefaultHKT> = Set>; /** - * Deep merge 2 maps. + * Deep merge maps. */ type DeepMergeMapsDefaultHKT> = Map, UnionMapValues>; /** * Get the merge functions with defaults apply from the given subset. */ type GetDeepMergeMergeFunctionsURIs> = Readonly<{ + // prettier-ignore DeepMergeRecordsURI: PMF["DeepMergeRecordsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeRecordsURI"] : DeepMergeRecordsDefaultURI; + // prettier-ignore DeepMergeArraysURI: PMF["DeepMergeArraysURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeArraysURI"] : DeepMergeArraysDefaultURI; + // prettier-ignore DeepMergeSetsURI: PMF["DeepMergeSetsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeSetsURI"] : DeepMergeSetsDefaultURI; + // prettier-ignore DeepMergeMapsURI: PMF["DeepMergeMapsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeMapsURI"] : DeepMergeMapsDefaultURI; + // prettier-ignore DeepMergeOthersURI: PMF["DeepMergeOthersURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeOthersURI"] : DeepMergeLeafURI; }>; - /** * The default merge functions. */ -type MergeFunctions$1 = { - mergeRecords: typeof mergeRecords$1; - mergeArrays: typeof mergeArrays$1; - mergeSets: typeof mergeSets$1; - mergeMaps: typeof mergeMaps$1; - mergeOthers: typeof mergeOthers$1; +type MergeFunctions = { + mergeRecords: typeof mergeRecords; + mergeArrays: typeof mergeArrays; + mergeSets: typeof mergeSets; + mergeMaps: typeof mergeMaps; + mergeOthers: typeof mergeOthers; }; /** * The default strategy to merge records into a target record. @@ -325,72 +562,43 @@ type MergeFunctions$1 = { * @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$1>, U extends DeepMergeMergeIntoFunctionUtils, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData>(m_target: Reference>, values: Ts, utils: U, meta: M | undefined): void; +declare function mergeRecords>, U extends DeepMergeMergeIntoFunctionUtils, 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. * * @param m_target - The result will be mutated into this array * @param values - The arrays (including the target's value if there is one). */ -declare function mergeArrays$1>>(m_target: Reference, values: Ts): void; +declare function mergeArrays>>(m_target: Reference, values: Ts): void; /** * The default strategy to merge sets into a target set. * * @param m_target - The result will be mutated into this set * @param values - The sets (including the target's value if there is one). */ -declare function mergeSets$1>>>(m_target: Reference>, values: Ts): void; +declare function mergeSets>>>(m_target: Reference>, values: Ts): void; /** * The default strategy to merge maps into a target map. * * @param m_target - The result will be mutated into this map * @param values - The maps (including the target's value if there is one). */ -declare function mergeMaps$1>>>(m_target: Reference>, values: Ts): void; +declare function mergeMaps>>>(m_target: Reference>, values: Ts): void; /** - * Set the target to the last value. + * Set the target to the last non-undefined value. */ -declare function mergeOthers$1>(m_target: Reference, values: Ts): void; - +declare function mergeOthers>(m_target: Reference, values: Ts): void; +type MergeIntoFunctions = MergeFunctions; /** * The default merge functions. */ -type MergeFunctions = { +type MergeFunctions$0 = { mergeRecords: typeof mergeRecords; mergeArrays: typeof mergeArrays; mergeSets: typeof mergeSets; mergeMaps: typeof mergeMaps; mergeOthers: typeof mergeOthers; }; -/** - * The default strategy to merge records. - * - * @param values - The records. - */ -declare function mergeRecords>, U extends DeepMergeMergeFunctionUtils, MF extends DeepMergeMergeFunctionsURIs, M, MM extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData>(values: Ts, utils: U, meta: M | undefined): DeepMergeRecordsDefaultHKT; -/** - * The default strategy to merge arrays. - * - * @param values - The arrays. - */ -declare function mergeArrays>, MF extends DeepMergeMergeFunctionsURIs, M>(values: Ts): DeepMergeArraysDefaultHKT; -/** - * The default strategy to merge sets. - * - * @param values - The sets. - */ -declare function mergeSets>>>(values: Ts): DeepMergeSetsDefaultHKT; -/** - * The default strategy to merge maps. - * - * @param values - The maps. - */ -declare function mergeMaps>>>(values: Ts): DeepMergeMapsDefaultHKT; -/** - * Get the last value in the given array. - */ -declare function mergeOthers>(values: Ts): unknown; - /** * The options the user can pass to customize deepmerge. */ @@ -439,6 +647,7 @@ type DeepMergeMergeFunctions>>, U extends DeepMergeMergeFunctionUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; mergeOthers: , U extends DeepMergeMergeFunctionUtils>(values: Ts, utils: U, meta: M | undefined) => unknown; }>; +// eslint-disable-next-line ts/no-invalid-void-type type DeepMergeMergeIntoFunctionsReturnType = void | symbol; /** * All the merge functions that deepmerge uses. @@ -455,7 +664,7 @@ type DeepMergeMergeIntoFunctions = Readonly<{ mergeFunctions: DeepMergeMergeFunctions; - defaultMergeFunctions: MergeFunctions; + defaultMergeFunctions: MergeFunctions$0; metaDataUpdater: MetaDataUpdater; deepmerge: >(...values: Ts) => unknown; useImplicitDefaultMerging: boolean; @@ -469,34 +678,34 @@ type DeepMergeMergeFunctionUtils = Readonly<{ mergeFunctions: DeepMergeMergeIntoFunctions; - defaultMergeFunctions: MergeFunctions$1; + defaultMergeFunctions: MergeIntoFunctions; metaDataUpdater: MetaDataUpdater; deepmergeInto: >(target: Target, ...values: Ts) => void; actions: Readonly<{ defaultMerge: symbol; }>; }>; - /** * Deeply merge objects. * * @param objects - The objects to merge. */ -declare function deepmerge>>(...objects: readonly [...Ts]): DeepMergeHKT; +declare function deepmerge>>(...objects: readonly [ + ...Ts +]): 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, 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. * @@ -510,7 +719,7 @@ declare function deepmergeInto(target: T, ...objects: Readonly * @param target - This object will be mutated with the merge result. * @param objects - The objects to merge into the target. */ -declare function deepmergeInto>(target: Target, ...objects: Ts): asserts target is FlatternAlias>(target: Target, ...objects: Ts): asserts target is SimplifyObject>; @@ -519,15 +728,14 @@ declare function deepmergeInto): >(target: Target, ...objects: Ts) => void; +declare function deepmergeIntoCustom(options: DeepMergeIntoOptions): >(target: Target, ...objects: Ts) => void; /** * 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 deepmergeIntoCustom(options: DeepMergeIntoOptions, rootMetaData?: MetaData): >(target: Target, ...objects: Ts) => void; - +declare function deepmergeIntoCustom(options: DeepMergeIntoOptions, rootMetaData?: MetaData): >(target: Target, ...objects: Ts) => void; /** * The different types of objects deepmerge-ts support. */ @@ -563,5 +771,5 @@ declare function getKeys(objects: ReadonlyArray): Set; * @returns Whether the object has the property. */ declare function objectHasProperty(object: object, property: PropertyKey): boolean; - -export { DeepMergeArraysDefaultHKT, DeepMergeBuiltInMetaData, DeepMergeHKT, DeepMergeIntoOptions, DeepMergeLeaf, DeepMergeLeafHKT, DeepMergeLeafURI, DeepMergeMapsDefaultHKT, DeepMergeMergeFunctionURItoKind, DeepMergeMergeFunctionUtils, DeepMergeMergeFunctionsDefaultURIs, MergeFunctions as DeepMergeMergeFunctionsDefaults, DeepMergeMergeFunctionsURIs, DeepMergeMergeIntoFunctionUtils, MergeFunctions$1 as DeepMergeMergeIntoFunctionsDefaults, DeepMergeOptions, DeepMergeRecordsDefaultHKT, DeepMergeSetsDefaultHKT, Reference as DeepMergeValueReference, GetDeepMergeMergeFunctionsURIs, ObjectType, deepmerge, deepmergeCustom, deepmergeInto, deepmergeIntoCustom, getKeys, getObjectType, objectHasProperty }; +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 }; diff --git a/dist/node/index.mjs b/dist/node/index.mjs index 70e5e1dd..3080703f 100644 --- a/dist/node/index.mjs +++ b/dist/node/index.mjs @@ -19,6 +19,18 @@ function defaultMetaDataUpdater(previousMeta, metaMeta) { return metaMeta; } +/** + * The different types of objects deepmerge-ts support. + */ +var ObjectType; +(function (ObjectType) { + ObjectType[ObjectType["NOT"] = 0] = "NOT"; + ObjectType[ObjectType["RECORD"] = 1] = "RECORD"; + ObjectType[ObjectType["ARRAY"] = 2] = "ARRAY"; + ObjectType[ObjectType["SET"] = 3] = "SET"; + ObjectType[ObjectType["MAP"] = 4] = "MAP"; + ObjectType[ObjectType["OTHER"] = 5] = "OTHER"; +})(ObjectType || (ObjectType = {})); /** * Get the type of the given object. * @@ -53,7 +65,6 @@ function getObjectType(object) { */ function getKeys(objects) { const keys = new Set(); - /* eslint-disable functional/no-loop-statements, functional/no-expression-statements -- using a loop here is more efficient. */ for (const object of objects) { for (const key of [ ...Object.keys(object), @@ -62,7 +73,6 @@ function getKeys(objects) { keys.add(key); } } - /* eslint-enable functional/no-loop-statements, functional/no-expression-statements */ return keys; } /** @@ -81,11 +91,8 @@ function objectHasProperty(object, property) { */ function getIterableOfIterables(iterables) { return { - // eslint-disable-next-line functional/functional-parameters *[Symbol.iterator]() { - // eslint-disable-next-line functional/no-loop-statements for (const iterable of iterables) { - // eslint-disable-next-line functional/no-loop-statements for (const value of iterable) { yield value; } @@ -107,11 +114,10 @@ function isRecord(value) { } const { constructor } = value; // If has modified constructor. - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + // eslint-disable-next-line ts/no-unnecessary-condition if (constructor === undefined) { return true; } - // eslint-disable-next-line prefer-destructuring const prototype = constructor.prototype; // If has modified prototype. if (prototype === null || @@ -120,7 +126,7 @@ function isRecord(value) { return false; } // If constructor does not have an Object-specific method. - // eslint-disable-next-line sonarjs/prefer-single-boolean-return, no-prototype-builtins + // eslint-disable-next-line sonar/prefer-single-boolean-return, no-prototype-builtins if (!prototype.hasOwnProperty("isPrototypeOf")) { return false; } @@ -135,7 +141,6 @@ function isRecord(value) { */ function mergeRecords$2(values, utils, meta) { const result = {}; - /* eslint-disable functional/no-loop-statements, functional/no-conditional-statements, functional/no-expression-statements, functional/immutable-data -- using imperative code here is more performant. */ for (const key of getKeys(values)) { const propValues = []; for (const value of values) { @@ -166,7 +171,6 @@ function mergeRecords$2(values, utils, meta) { result[key] = propertyResult; } } - /* eslint-enable functional/no-loop-statements, functional/no-conditional-statements, functional/no-expression-statements, functional/immutable-data */ return result; } /** @@ -194,19 +198,24 @@ function mergeMaps$2(values) { return new Map(getIterableOfIterables(values)); } /** - * Get the last value in the given array. + * Get the last non-undefined value in the given array. */ function mergeOthers$2(values) { - return values.at(-1); + for (let i = values.length - 1; i >= 0; i--) { + if (values[i] !== undefined) { + return values[i]; + } + } + return undefined; } var defaultMergeFunctions = /*#__PURE__*/Object.freeze({ - __proto__: null, - mergeArrays: mergeArrays$2, - mergeMaps: mergeMaps$2, - mergeOthers: mergeOthers$2, - mergeRecords: mergeRecords$2, - mergeSets: mergeSets$2 + __proto__: null, + mergeArrays: mergeArrays$2, + mergeMaps: mergeMaps$2, + mergeOthers: mergeOthers$2, + mergeRecords: mergeRecords$2, + mergeSets: mergeSets$2 }); /** @@ -214,9 +223,7 @@ var defaultMergeFunctions = /*#__PURE__*/Object.freeze({ * * @param objects - The objects to merge. */ -function deepmerge( -// eslint-disable-next-line functional/functional-parameters -...objects) { +function deepmerge(...objects) { return deepmergeCustom({})(...objects); } function deepmergeCustom(options, rootMetaData) { @@ -224,9 +231,7 @@ function deepmergeCustom(options, rootMetaData) { /** * The customized deepmerge function. */ - function customizedDeepmerge( - // eslint-disable-next-line functional/functional-parameters - ...objects) { + function customizedDeepmerge(...objects) { return mergeUnknowns(objects, utils, rootMetaData); } return customizedDeepmerge; @@ -267,7 +272,6 @@ function mergeUnknowns(values, utils, meta) { return mergeOthers$1(values, utils, meta); } const type = getObjectType(values[0]); - /* eslint-disable functional/no-loop-statements, functional/no-conditional-statements -- using imperative code here is more performant. */ 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) { @@ -276,7 +280,6 @@ function mergeUnknowns(values, utils, meta) { return mergeOthers$1(values, utils, meta); } } - /* eslint-enable functional/no-loop-statements, functional/no-conditional-statements */ switch (type) { case 1 /* ObjectType.RECORD */: { return mergeRecords$1(values, utils, meta); @@ -442,19 +445,25 @@ function mergeMaps(m_target, values) { } } /** - * Set the target to the last value. + * Set the target to the last non-undefined value. */ function mergeOthers(m_target, values) { - m_target.value = values.at(-1); + for (let i = values.length - 1; i >= 0; i--) { + if (values[i] !== undefined) { + m_target.value = values[i]; + return; + } + } + m_target.value = undefined; } var defaultMergeIntoFunctions = /*#__PURE__*/Object.freeze({ - __proto__: null, - mergeArrays: mergeArrays, - mergeMaps: mergeMaps, - mergeOthers: mergeOthers, - mergeRecords: mergeRecords, - mergeSets: mergeSets + __proto__: null, + mergeArrays: mergeArrays, + mergeMaps: mergeMaps, + mergeOthers: mergeOthers, + mergeRecords: mergeRecords, + mergeSets: mergeSets }); function deepmergeInto(target, ...objects) { @@ -498,9 +507,7 @@ function getIntoUtils(options, customizedDeepmergeInto) { * @param m_target - The target to merge into. * @param values - The values. */ -function mergeUnknownsInto(m_target, values, utils, meta -// eslint-disable-next-line @typescript-eslint/no-invalid-void-type -) { +function mergeUnknownsInto(m_target, values, utils, meta) { if (values.length === 0) { return; } diff --git a/dist/node/types/legacy/v4_0.d.ts b/dist/node/types/legacy/v4_0.d.ts deleted file mode 100644 index 7a30a0a1..00000000 --- a/dist/node/types/legacy/v4_0.d.ts +++ /dev/null @@ -1,80 +0,0 @@ -/** - * @file - * - * These types are a more simplified version of this library's types - * designed to work with versions of TypeScript < 4.1 - */ - -declare type MetaDataUpdater = (previousMeta: any, metaMeta: any) => any; - -/** - * All the options the user can pass to customize deepmerge. - */ -declare type DeepMergeOptionsFull = Readonly<{ - mergeRecords: DeepMergeMergeFunctions["mergeRecords"] | false; - mergeArrays: DeepMergeMergeFunctions["mergeArrays"] | false; - mergeMaps: DeepMergeMergeFunctions["mergeMaps"] | false; - mergeSets: DeepMergeMergeFunctions["mergeSets"] | false; - mergeOthers: DeepMergeMergeFunctions["mergeOthers"]; - metaDataUpdater: MetaDataUpdater; -}>; - -/** - * All the merge functions that deepmerge uses. - */ -declare type DeepMergeMergeFunctions = Readonly<{ - mergeRecords: >>, U extends DeepMergeMergeFunctionUtils>(records: Ts, utils: U, meta: any) => any; - mergeArrays: >, U extends DeepMergeMergeFunctionUtils>(records: Ts, utils: U, meta: any) => any; - mergeMaps: >>, U extends DeepMergeMergeFunctionUtils>(records: Ts, utils: U, meta: any) => any; - mergeSets: >>, U extends DeepMergeMergeFunctionUtils>(records: Ts, utils: U, meta: any) => any; - mergeOthers: , U extends DeepMergeMergeFunctionUtils>(records: Ts, utils: U, meta: any) => any; -}>; - -/** - * The utils provided to the merge functions. - */ -declare type DeepMergeMergeFunctionUtils = Readonly<{ - mergeFunctions: DeepMergeMergeFunctions; - defaultMergeFunctions: DeepMergeMergeFunctionsDefaults; - metaDataUpdater: MetaDataUpdater; - deepmerge: >(...values: Ts) => any; -}>; - -/** - * The default merge functions. - */ -declare type DeepMergeMergeFunctionsDefaults = Readonly<{ - mergeMaps: (values: Record[]) => any; - mergeSets: (values: any[][]) => any; - mergeArrays: (values: Set[]) => any; - mergeRecords: (values: Map[], utils: DeepMergeMergeFunctionUtils, meta: any) => any; - mergeOthers: (values: any[]) => any; -}>; - -/** - * Deeply merge objects. - * - * @param objects - The objects to merge. - */ -declare function deepmerge(): undefined; -declare function deepmerge(arg0: T0): T0; -declare function deepmerge(arg0: T0, arg1: T1): T0 & T1; -declare function deepmerge(arg0: T0, arg1: T1, arg2: T2): T0 & T1 & T2; -declare function deepmerge(arg0: T0, arg1: T1, arg2: T2, arg3: T3): T0 & T1 & T2 & T3; -declare function deepmerge(arg0: T0, arg1: T1, arg2: T2, arg3: T3, arg4: T4): T0 & T1 & T2 & T3 & T4; -declare function deepmerge(arg0: T0, arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5): T0 & T1 & T2 & T3 & T4 & T5; -declare function deepmerge(arg0: T0, arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6): T0 & T1 & T2 & T3 & T4 & T5 & T6; -declare function deepmerge(arg0: T0, arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6, arg7: T7): T0 & T1 & T2 & T3 & T4 & T5 & T6 & T7; -declare function deepmerge(arg0: T0, arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6, arg7: T7, arg8: T8): T0 & T1 & T2 & T3 & T4 & T5 & T6 & T7 & T8; -declare function deepmerge(arg0: T0, arg1: T1, arg2: T2, arg3: T3, arg4: T4, arg5: T5, arg6: T6, arg7: T7, arg8: T8, arg9: T9): T0 & T1 & T2 & T3 & T4 & T5 & T6 & T7 & T8 & T9; -declare function deepmerge(...args: any[]): any; - -/** - * 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(options: Partial, rootMetaData?: any): (...objects: any[]) => any; - -export { deepmerge, deepmergeCustom }; diff --git a/dist/node/types/legacy/v4_6.d.ts b/dist/node/types/legacy/v4_6.d.ts deleted file mode 100644 index 6738d013..00000000 --- a/dist/node/types/legacy/v4_6.d.ts +++ /dev/null @@ -1,407 +0,0 @@ -/** - * Flatten a complex type such as a union or intersection of objects into a - * single object. - */ -declare type FlatternAlias = { - [P in keyof T]: T[P]; -} & {}; -/** - * Get the value of the given key in the given object. - */ -declare type ValueOfKey, K extends PropertyKey> = K extends keyof T ? T[K] : never; -/** - * Safely test whether or not the first given types extends the second. - * - * Needed in particular for testing if a type is "never". - */ -declare type Is = [T1] extends [T2] ? true : false; -/** - * Safely test whether or not the given type is "never". - */ -declare type IsNever = Is; -/** - * Returns whether or not the given type a record. - */ -declare type IsRecord = And>, T extends Readonly> ? true : false>; -/** - * Returns whether or not all the given types are records. - */ -declare type EveryIsRecord> = Ts extends readonly [infer Head, ...infer Rest] ? IsRecord extends true ? Rest extends ReadonlyArray ? EveryIsRecord : true : false : true; -/** - * Returns whether or not the given type is an array. - */ -declare type IsArray = And>, T extends ReadonlyArray ? true : false>; -/** - * Returns whether or not all the given types are arrays. - */ -declare type EveryIsArray> = Ts extends readonly [infer T1] ? IsArray : Ts extends readonly [infer Head, ...infer Rest] ? IsArray extends true ? Rest extends readonly [unknown, ...ReadonlyArray] ? EveryIsArray : false : false : false; -/** - * Returns whether or not the given type is an set. - * - * Note: This may also return true for Maps. - */ -declare type IsSet = And>, T extends Readonly> ? true : false>; -/** - * Returns whether or not all the given types are sets. - * - * Note: This may also return true if all are maps. - */ -declare type EveryIsSet> = Ts extends Readonly ? IsSet : Ts extends readonly [infer Head, ...infer Rest] ? IsSet extends true ? Rest extends readonly [unknown, ...ReadonlyArray] ? EveryIsSet : false : false : false; -/** - * Returns whether or not the given type is an map. - */ -declare type IsMap = And>, T extends Readonly> ? true : false>; -/** - * Returns whether or not all the given types are maps. - */ -declare type EveryIsMap> = Ts extends Readonly ? IsMap : Ts extends readonly [infer Head, ...infer Rest] ? IsMap extends true ? Rest extends readonly [unknown, ...ReadonlyArray] ? EveryIsMap : false : false : false; -/** - * And operator for types. - */ -declare type And = T1 extends false ? false : T2; -/** - * Not operator for types. - */ -declare type Not = T extends true ? false : true; -/** - * Union of the sets' values' types - */ -declare type UnionSetValues> = UnionSetValuesHelper; -/** - * Tail-recursive helper type for UnionSetValues. - */ -declare type UnionSetValuesHelper, Acc> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Readonly> ? Rest extends ReadonlyArray ? UnionSetValuesHelper : Acc | V1 : never : Acc; -/** - * Union of the maps' values' types - */ -declare type UnionMapKeys> = UnionMapKeysHelper; -/** - * Tail-recursive helper type for UnionMapKeys. - */ -declare type UnionMapKeysHelper, Acc> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Readonly> ? Rest extends readonly [] ? Acc | K1 : UnionMapKeysHelper : never : Acc; -/** - * Union of the maps' keys' types - */ -declare type UnionMapValues> = UnionMapValuesHelper; -/** - * Tail-recursive helper type for UnionMapValues. - */ -declare type UnionMapValuesHelper, Acc> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Readonly> ? Rest extends readonly [] ? Acc | V1 : UnionMapValuesHelper : never : Acc; -/** - * Get the keys of the type what match a certain criteria. - */ -declare type KeysOfType = { - [K in keyof T]: T[K] extends U ? K : never; -}[keyof T]; -/** - * Get the required keys of the type. - */ -declare type RequiredKeys = Exclude>, undefined>; -/** - * Get all the required keys on the types in the tuple. - */ -declare type RequiredKeysOf]> = RequiredKeysOfHelper; -/** - * Tail-recursive helper type for RequiredKeysOf. - */ -declare type RequiredKeysOfHelper], Acc> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Record ? Rest extends readonly [unknown, ...ReadonlyArray] ? RequiredKeysOfHelper> : Acc | RequiredKeys : never : Acc; -/** - * Get the optional keys of the type. - */ -declare type OptionalKeys = Exclude>; -/** - * Get all the optional keys on the types in the tuple. - */ -declare type OptionalKeysOf]> = OptionalKeysOfHelper; -/** - * Tail-recursive helper type for OptionalKeysOf. - */ -declare type OptionalKeysOfHelper], Acc> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Record ? Rest extends readonly [unknown, ...ReadonlyArray] ? OptionalKeysOfHelper> : Acc | OptionalKeys : never : Acc; -/** - * Filter out nevers from a tuple. - */ -declare type FilterOutNever> = FilterOutNeverHelper; -/** - * Tail-recursive helper type for FilterOutNever. - */ -declare type FilterOutNeverHelper, Acc extends ReadonlyArray> = T extends readonly [] ? Acc : T extends readonly [infer Head, ...infer Rest] ? IsNever extends true ? FilterOutNeverHelper : FilterOutNeverHelper : T; -/** - * Is the type a tuple? - */ -declare type IsTuple> = T extends readonly [] ? true : T extends readonly [unknown, ...ReadonlyArray] ? true : false; - -/** - * Mapping of merge function URIs to the merge function type. - */ -interface DeepMergeMergeFunctionURItoKind, MF extends DeepMergeMergeFunctionsURIs, M> { - readonly DeepMergeLeafURI: DeepMergeLeaf; - readonly DeepMergeRecordsDefaultURI: DeepMergeRecordsDefaultHKT; - readonly DeepMergeArraysDefaultURI: DeepMergeArraysDefaultHKT; - readonly DeepMergeSetsDefaultURI: DeepMergeSetsDefaultHKT; - readonly DeepMergeMapsDefaultURI: DeepMergeMapsDefaultHKT; -} -/** - * Get the type of the given merge function via its URI. - */ -declare type DeepMergeMergeFunctionKind, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionURItoKind[URI]; -/** - * A union of all valid merge function URIs. - */ -declare type DeepMergeMergeFunctionURIs = keyof DeepMergeMergeFunctionURItoKind, DeepMergeMergeFunctionsURIs, unknown>; -/** - * The merge functions to use when deep merging. - */ -declare type DeepMergeMergeFunctionsURIs = Readonly<{ - /** - * The merge function to merge records with. - */ - DeepMergeRecordsURI: DeepMergeMergeFunctionURIs; - /** - * The merge function to merge arrays with. - */ - DeepMergeArraysURI: DeepMergeMergeFunctionURIs; - /** - * The merge function to merge sets with. - */ - DeepMergeSetsURI: DeepMergeMergeFunctionURIs; - /** - * The merge function to merge maps with. - */ - DeepMergeMapsURI: DeepMergeMergeFunctionURIs; - /** - * The merge function to merge other things with. - */ - DeepMergeOthersURI: DeepMergeMergeFunctionURIs; -}>; -/** - * Deep merge types. - */ -declare type DeepMergeHKT, MF extends DeepMergeMergeFunctionsURIs, 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 : unknown; -/** - * Deep merge records. - */ -declare type DeepMergeRecordsHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionKind; -/** - * Deep merge arrays. - */ -declare type DeepMergeArraysHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionKind; -/** - * Deep merge sets. - */ -declare type DeepMergeSetsHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionKind; -/** - * Deep merge maps. - */ -declare type DeepMergeMapsHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionKind; -/** - * Deep merge other things. - */ -declare type DeepMergeOthersHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeMergeFunctionKind; -/** - * The merge function that returns a leaf. - */ -declare type DeepMergeLeafURI = "DeepMergeLeafURI"; -/** - * Get the leaf type from many types that can't be merged. - * - * @deprecated Use `DeepMergeLeaf` instead. - */ -declare type DeepMergeLeafHKT> = DeepMergeLeaf; -/** - * Get the leaf type from many types that can't be merged. - */ -declare type DeepMergeLeaf> = Ts extends readonly [] ? never : Ts extends readonly [infer T] ? T : Ts extends readonly [...infer Rest, infer Tail] ? IsNever extends true ? Rest extends ReadonlyArray ? DeepMergeLeaf : never : Tail : never; -/** - * The meta data deepmerge is able to provide. - */ -declare type DeepMergeBuiltInMetaData = Readonly<{ - key: PropertyKey; - parents: ReadonlyArray>>; -}>; - -/** - * The default merge function to merge records with. - */ -declare type DeepMergeRecordsDefaultURI = "DeepMergeRecordsDefaultURI"; -/** - * The default merge function to merge arrays with. - */ -declare type DeepMergeArraysDefaultURI = "DeepMergeArraysDefaultURI"; -/** - * The default merge function to merge sets with. - */ -declare type DeepMergeSetsDefaultURI = "DeepMergeSetsDefaultURI"; -/** - * The default merge function to merge maps with. - */ -declare type DeepMergeMapsDefaultURI = "DeepMergeMapsDefaultURI"; -/** - * The default merge functions to use when deep merging. - */ -declare type DeepMergeMergeFunctionsDefaultURIs = Readonly<{ - DeepMergeRecordsURI: DeepMergeRecordsDefaultURI; - DeepMergeArraysURI: DeepMergeArraysDefaultURI; - DeepMergeSetsURI: DeepMergeSetsDefaultURI; - DeepMergeMapsURI: DeepMergeMapsDefaultURI; - DeepMergeOthersURI: DeepMergeLeafURI; -}>; -/** - * A union of all the props that should not be included in type information for - * merged records. - */ -declare type BlacklistedRecordProps = "__proto__"; -/** - * Deep merge records. - */ -declare type DeepMergeRecordsDefaultHKT, MF extends DeepMergeMergeFunctionsURIs, M> = Ts extends Readonly>]> ? FlatternAlias, BlacklistedRecordProps>> : {}; -/** - * Deep merge record props. - */ -declare type DeepMergeRecordsDefaultHKTInternalProps], MF extends DeepMergeMergeFunctionsURIs, M> = { - [K in OptionalKeysOf]?: DeepMergeHKT, MF, M>; -} & { - [K in RequiredKeysOf]: DeepMergeHKT, MF, M>; -}; -/** - * Get the value of the property. - */ -declare type DeepMergeRecordsDefaultHKTInternalPropValue], K extends PropertyKey, M> = FilterOutNever>; -/** - * Tail-recursive helper type for DeepMergeRecordsDefaultHKTInternalPropValue. - */ -declare type DeepMergeRecordsDefaultHKTInternalPropValueHelper], K extends PropertyKey, M, Acc extends ReadonlyArray> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends Readonly> ? Rest extends readonly [unknown, ...ReadonlyArray] ? DeepMergeRecordsDefaultHKTInternalPropValueHelper -]> : [...Acc, ValueOfKey] : never : never; -/** - * Deep merge 2 arrays. - */ -declare type DeepMergeArraysDefaultHKT, MF extends DeepMergeMergeFunctionsURIs, M> = DeepMergeArraysDefaultHKTHelper; -/** - * Tail-recursive helper type for DeepMergeArraysDefaultHKT. - */ -declare type DeepMergeArraysDefaultHKTHelper, MF extends DeepMergeMergeFunctionsURIs, M, Acc extends ReadonlyArray> = Ts extends readonly [infer Head, ...infer Rest] ? Head extends ReadonlyArray ? Rest extends readonly [ - ReadonlyArray, - ...ReadonlyArray> -] ? DeepMergeArraysDefaultHKTHelper : [...Acc, ...Head] : never : never; -/** - * Deep merge 2 sets. - */ -declare type DeepMergeSetsDefaultHKT> = Set>; -/** - * Deep merge 2 maps. - */ -declare type DeepMergeMapsDefaultHKT> = Map, UnionMapValues>; -/** - * Get the merge functions with defaults apply from the given subset. - */ -declare type GetDeepMergeMergeFunctionsURIs> = Readonly<{ - DeepMergeRecordsURI: PMF["DeepMergeRecordsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeRecordsURI"] : DeepMergeRecordsDefaultURI; - DeepMergeArraysURI: PMF["DeepMergeArraysURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeArraysURI"] : DeepMergeArraysDefaultURI; - DeepMergeSetsURI: PMF["DeepMergeSetsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeSetsURI"] : DeepMergeSetsDefaultURI; - DeepMergeMapsURI: PMF["DeepMergeMapsURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeMapsURI"] : DeepMergeMapsDefaultURI; - DeepMergeOthersURI: PMF["DeepMergeOthersURI"] extends keyof DeepMergeMergeFunctionURItoKind ? PMF["DeepMergeOthersURI"] : DeepMergeLeafURI; -}>; - -/** - * The options the user can pass to customize deepmerge. - */ -declare type DeepMergeOptions> = DeepMergeBuiltInMetaData> = Partial>; -declare type MetaDataUpdater = (previousMeta: M | undefined, metaMeta: Readonly>) => M; -/** - * All the options the user can pass to customize deepmerge. - */ -declare type DeepMergeOptionsFull = Readonly<{ - mergeRecords: DeepMergeMergeFunctions["mergeRecords"] | false; - mergeArrays: DeepMergeMergeFunctions["mergeArrays"] | false; - mergeMaps: DeepMergeMergeFunctions["mergeMaps"] | false; - mergeSets: DeepMergeMergeFunctions["mergeSets"] | false; - mergeOthers: DeepMergeMergeFunctions["mergeOthers"]; - metaDataUpdater: MetaDataUpdater; - enableImplicitDefaultMerging: boolean; -}>; -/** - * All the merge functions that deepmerge uses. - */ -declare type DeepMergeMergeFunctions = Readonly<{ - mergeRecords: >>, U extends DeepMergeMergeFunctionUtils>(records: Ts, utils: U, meta: M | undefined) => unknown; - mergeArrays: >, U extends DeepMergeMergeFunctionUtils>(records: Ts, utils: U, meta: M | undefined) => unknown; - mergeMaps: >>, U extends DeepMergeMergeFunctionUtils>(records: Ts, utils: U, meta: M | undefined) => unknown; - mergeSets: >>, U extends DeepMergeMergeFunctionUtils>(records: Ts, utils: U, meta: M | undefined) => unknown; - mergeOthers: , U extends DeepMergeMergeFunctionUtils>(records: Ts, utils: U, meta: M | undefined) => unknown; -}>; -/** - * The utils provided to the merge functions. - */ -declare type DeepMergeMergeFunctionUtils = Readonly<{ - mergeFunctions: DeepMergeMergeFunctions; - defaultMergeFunctions: DeepMergeMergeFunctionsDefaults; - metaDataUpdater: MetaDataUpdater; - deepmerge: >(...values: Ts) => unknown; - useImplicitDefaultMerging: boolean; - actions: Readonly<{ - defaultMerge: symbol; - skip: symbol; - }>; -}>; - -declare const defaultMergeFunctions: { - readonly mergeMaps: typeof defaultMergeMaps; - readonly mergeSets: typeof defaultMergeSets; - readonly mergeArrays: typeof defaultMergeArrays; - readonly mergeRecords: typeof defaultMergeRecords; - readonly mergeOthers: typeof leaf; -}; -/** - * The default merge functions. - */ -declare type DeepMergeMergeFunctionsDefaults = typeof defaultMergeFunctions; -/** - * Deeply merge objects. - * - * @param objects - The objects to merge. - */ -declare function deepmerge>>(...objects: readonly [...Ts]): 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>; -/** - * 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, MetaMetaData extends DeepMergeBuiltInMetaData = DeepMergeBuiltInMetaData>(options: DeepMergeOptions, rootMetaData?: MetaData): >(...objects: Ts) => DeepMergeHKT, MetaData>; -/** - * The default strategy to merge records. - * - * @param values - The records. - */ -declare function defaultMergeRecords>, U extends DeepMergeMergeFunctionUtils, MF extends DeepMergeMergeFunctionsURIs, M, MM extends DeepMergeBuiltInMetaData>(values: Ts, utils: U, meta: M | undefined): DeepMergeRecordsDefaultHKT; -/** - * The default strategy to merge arrays. - * - * @param values - The arrays. - */ -declare function defaultMergeArrays>, MF extends DeepMergeMergeFunctionsURIs, M>(values: Ts): DeepMergeArraysDefaultHKT; -/** - * The default strategy to merge sets. - * - * @param values - The sets. - */ -declare function defaultMergeSets>>>(values: Ts): DeepMergeSetsDefaultHKT; -/** - * The default strategy to merge maps. - * - * @param values - The maps. - */ -declare function defaultMergeMaps>>>(values: Ts): DeepMergeMapsDefaultHKT; -/** - * Get the last value in the given array. - */ -declare function leaf>(values: Ts): unknown; - -export { DeepMergeArraysDefaultHKT, DeepMergeBuiltInMetaData, DeepMergeHKT, DeepMergeLeaf, DeepMergeLeafHKT, DeepMergeLeafURI, DeepMergeMapsDefaultHKT, DeepMergeMergeFunctionURItoKind, DeepMergeMergeFunctionUtils, DeepMergeMergeFunctionsDefaultURIs, DeepMergeMergeFunctionsDefaults, DeepMergeMergeFunctionsURIs, DeepMergeOptions, DeepMergeRecordsDefaultHKT, DeepMergeSetsDefaultHKT, deepmerge, deepmergeCustom };