From 45025bb2f12505d438610f0f4fbd25470f881b07 Mon Sep 17 00:00:00 2001 From: Felipe Cardoso Date: Tue, 6 Jan 2026 13:54:18 +0100 Subject: [PATCH] fix(forms): handle nullable fields in deepMergeWithDefaults MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When default value is null but source has a value (e.g., description field), the merge was discarding the source value because typeof null !== typeof string. Now properly accepts source values for nullable fields. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- frontend/src/lib/forms/utils/mergeWithDefaults.ts | 4 ++++ frontend/tests/lib/forms/utils/mergeWithDefaults.test.ts | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/frontend/src/lib/forms/utils/mergeWithDefaults.ts b/frontend/src/lib/forms/utils/mergeWithDefaults.ts index 203c906..3c6a389 100644 --- a/frontend/src/lib/forms/utils/mergeWithDefaults.ts +++ b/frontend/src/lib/forms/utils/mergeWithDefaults.ts @@ -111,6 +111,10 @@ export function deepMergeWithDefaults>( if (typeof sourceValue === typeof defaultValue) { result[key] = sourceValue as T[keyof T]; } + // Special case: default is null but source has a value (nullable fields) + else if (defaultValue === null && sourceValue !== null) { + result[key] = sourceValue as T[keyof T]; + } // Special case: allow null for nullable fields else if (sourceValue === null && defaultValue === null) { result[key] = null as T[keyof T]; diff --git a/frontend/tests/lib/forms/utils/mergeWithDefaults.test.ts b/frontend/tests/lib/forms/utils/mergeWithDefaults.test.ts index 86824ab..140f8ed 100644 --- a/frontend/tests/lib/forms/utils/mergeWithDefaults.test.ts +++ b/frontend/tests/lib/forms/utils/mergeWithDefaults.test.ts @@ -190,6 +190,15 @@ describe('deepMergeWithDefaults', () => { const source = { value: null }; expect(deepMergeWithDefaults(defaults, source)).toEqual({ value: null }); }); + + it('uses source value when default is null but source has value', () => { + const defaults = { description: null as string | null, name: '' }; + const source = { description: 'A real description', name: 'Test' }; + expect(deepMergeWithDefaults(defaults, source)).toEqual({ + description: 'A real description', + name: 'Test', + }); + }); }); describe('createFormInitializer', () => {