From 9c866054cbade77118b5cd62b1e8e68033fe2879 Mon Sep 17 00:00:00 2001 From: Rebecca Stevens Date: Fri, 10 May 2024 19:03:47 +1200 Subject: [PATCH] feat!: undefined will no longer replace defined values by default --- src/defaults/into.ts | 10 ++++++++-- src/defaults/vanilla.ts | 9 +++++++-- src/types/merging.ts | 4 +++- tests/deepmerge-into.test.ts | 4 ++-- tests/deepmerge.test-d.ts | 2 +- tests/deepmerge.test.ts | 6 +++--- 6 files changed, 24 insertions(+), 11 deletions(-) diff --git a/src/defaults/into.ts b/src/defaults/into.ts index 86a7d4d8..89cba226 100644 --- a/src/defaults/into.ts +++ b/src/defaults/into.ts @@ -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, ) { - 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/src/defaults/vanilla.ts b/src/defaults/vanilla.ts index 6c859940..91b2d303 100644 --- a/src/defaults/vanilla.ts +++ b/src/defaults/vanilla.ts @@ -119,8 +119,13 @@ export function mergeMaps< } /** - * 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/src/types/merging.ts b/src/types/merging.ts index 9f5986b9..735fee8f 100644 --- a/src/types/merging.ts +++ b/src/types/merging.ts @@ -9,8 +9,10 @@ import { type EveryIsMap, type EveryIsRecord, type EveryIsSet, + type Is, type IsNever, type IsTuple, + type Or, } from "./utils"; /** @@ -169,7 +171,7 @@ export type DeepMergeLeaf> = : Ts extends readonly [infer T] ? T : Ts extends readonly [...infer Rest, infer Tail] - ? IsNever extends true + ? Or, Is> extends true ? Rest extends ReadonlyArray ? DeepMergeLeaf : never diff --git a/tests/deepmerge-into.test.ts b/tests/deepmerge-into.test.ts index 619221c6..e673c2fb 100644 --- a/tests/deepmerge-into.test.ts +++ b/tests/deepmerge-into.test.ts @@ -266,11 +266,11 @@ describe("deepmergeInto", () => { expect(x).toStrictEqual(expected); }); - it(`replaces records with undefined`, () => { + it(`doesn't replaces records with undefined`, () => { const x = { key1: { subkey: `one` } }; const y = { key1: undefined }; - const expected = { key1: undefined }; + const expected = { key1: { subkey: `one` } }; deepmergeInto(x, y); diff --git a/tests/deepmerge.test-d.ts b/tests/deepmerge.test-d.ts index 8c2d651f..0fcaad12 100644 --- a/tests/deepmerge.test-d.ts +++ b/tests/deepmerge.test-d.ts @@ -163,7 +163,7 @@ const i = { }; const test13 = deepmerge(a, i); -expectType<{ foo: undefined; baz: { quux: string[] }; garply: number }>(test13); +expectType<{ foo: string; baz: { quux: string[] }; garply: number }>(test13); const j = { foo: new Set([1, 2]), diff --git a/tests/deepmerge.test.ts b/tests/deepmerge.test.ts index a5f75c10..6f799a63 100644 --- a/tests/deepmerge.test.ts +++ b/tests/deepmerge.test.ts @@ -300,18 +300,18 @@ describe("deepmerge", () => { const x = { key1: undefined }; const y = { key1: { subkey: `one` } }; - const expected = { key1: { subkey: `one` } }; + const expected = { key1: y.key1 }; const merged = deepmerge(x, y); expect(merged).toStrictEqual(expected); }); - it(`replaces records with undefined`, () => { + it(`doesn't replaces records with undefined`, () => { const x = { key1: { subkey: `one` } }; const y = { key1: undefined }; - const expected = { key1: undefined }; + const expected = { key1: x.key1 }; const merged = deepmerge(x, y);