diff --git a/src/types/DeepStrictMerge.ts b/src/types/DeepStrictMerge.ts index 8fa07c3..d40d651 100644 --- a/src/types/DeepStrictMerge.ts +++ b/src/types/DeepStrictMerge.ts @@ -29,21 +29,7 @@ namespace DeepStrictMerge { : Target[key] // If `Target` is not an object, take `Target`'s value : Target[key] // If `key` is only in `Target`, take `Target`'s value : key extends keyof Source - ? key extends keyof Target - ? Source[key] extends object - ? Source[key] extends Date - ? Target[key] // Date is a leaf type, Target wins - : Target[key] extends object - ? Target[key] extends Date - ? Target[key] // Target is Date leaf, preserve as-is - : Target[key] extends Array - ? Source[key] extends Array - ? Array> // If both are arrays of objects, merge their elements into a new array - : never // If one is an array and the other is not, merging is not possible - : Infer // If both are objects, merge them recursively - : Source[key] // If `Source` is an object but `Target` is not, take `Source`'s value - : Source[key] // If `Source` is not an object, take `Source`'s value - : Source[key] // If `key` is only in `Source`, take `Source`'s value + ? Source[key] // If `key` is only in `Source`, take `Source`'s value : never; // If `key` is in neither `Target` nor `Source`, return `never` }; } diff --git a/test/features/DeepStrictMerge.ts b/test/features/DeepStrictMerge.ts index 4e21ded..fd8c60f 100644 --- a/test/features/DeepStrictMerge.ts +++ b/test/features/DeepStrictMerge.ts @@ -118,3 +118,44 @@ export function test_types_deep_strict_merge_nested_date() { type Answer = Equal; ok(typia.random()); } + +/** + * Tests that a Source-only key with a Date value is taken directly from Source. + * This proves the dead-code branch (re-checking `key extends keyof Target`) was unreachable: + * if `key` is only in Source, the result must be `Source[key]` regardless of type. + */ +export function test_types_deep_strict_merge_source_only_date() { + type Question = DeepStrictMerge<{ a: number }, { createdAt: Date }>; + type Answer = Equal; + ok(typia.random()); +} + +/** + * Tests that a Source-only key with a nested object value is taken directly from Source. + * The dead code attempted to recursively merge Source[key] with Target[key], + * but Target[key] doesn't exist for Source-only keys. + */ +export function test_types_deep_strict_merge_source_only_nested_object() { + type Question = DeepStrictMerge<{ a: number }, { b: { c: string; d: boolean } }>; + type Answer = Equal; + ok(typia.random()); +} + +/** + * Tests that a Source-only key with an array-of-objects value is taken directly from Source. + * The dead code attempted to merge array elements, but that's impossible for Source-only keys. + */ +export function test_types_deep_strict_merge_source_only_array_of_objects() { + type Question = DeepStrictMerge<{ a: number }, { items: { id: number; name: string }[] }>; + type Answer = Equal; + ok(typia.random()); +} + +/** + * Tests that a Source-only key with a deeply nested object is taken as-is from Source. + */ +export function test_types_deep_strict_merge_source_only_deeply_nested_object() { + type Question = DeepStrictMerge<{ x: number }, { y: { z: { w: string; v: Date } } }>; + type Answer = Equal; + ok(typia.random()); +}