From 485abbf7e113b672c2e9f348165669e4c686b1af Mon Sep 17 00:00:00 2001 From: Raik Casimiro <71909221+raik-casimiro@users.noreply.github.com> Date: Tue, 16 Apr 2024 17:13:15 -0300 Subject: [PATCH] Bugfix: z.record().parse should not filter out undefined values (#3251) When calling .parse on z.record() we should not filter out undefined values. Add the optional 'alwaysSet' to the z.record pairs before passing them to mergeObject to maintain undefined values. This solves issue #3197 --- deno/lib/__tests__/record.test.ts | 8 ++++++++ deno/lib/types.ts | 2 ++ src/__tests__/record.test.ts | 8 ++++++++ src/types.ts | 2 ++ 4 files changed, 20 insertions(+) diff --git a/deno/lib/__tests__/record.test.ts b/deno/lib/__tests__/record.test.ts index ecb698af9..54849a4fa 100644 --- a/deno/lib/__tests__/record.test.ts +++ b/deno/lib/__tests__/record.test.ts @@ -171,3 +171,11 @@ test("is not vulnerable to prototype pollution", async () => { expect(obj4.data.a).toBeUndefined(); } }); + +test("dont parse undefined values", () => { + const result1 = z.record( z.any() ).parse( { foo: undefined } ); + + expect(result1).toEqual({ + foo: undefined, + }); +}) \ No newline at end of file diff --git a/deno/lib/types.ts b/deno/lib/types.ts index 9415fbe3f..249170af8 100644 --- a/deno/lib/types.ts +++ b/deno/lib/types.ts @@ -3504,6 +3504,7 @@ export class ZodRecord< const pairs: { key: ParseReturnType; value: ParseReturnType; + alwaysSet: boolean; }[] = []; const keyType = this._def.keyType; @@ -3515,6 +3516,7 @@ export class ZodRecord< value: valueType._parse( new ParseInputLazyPath(ctx, ctx.data[key], ctx.path, key) ), + alwaysSet: key in ctx.data, }); } diff --git a/src/__tests__/record.test.ts b/src/__tests__/record.test.ts index 7a773c748..7a7d71419 100644 --- a/src/__tests__/record.test.ts +++ b/src/__tests__/record.test.ts @@ -170,3 +170,11 @@ test("is not vulnerable to prototype pollution", async () => { expect(obj4.data.a).toBeUndefined(); } }); + +test("dont parse undefined values", () => { + const result1 = z.record( z.any() ).parse( { foo: undefined } ); + + expect(result1).toEqual({ + foo: undefined, + }); +}) \ No newline at end of file diff --git a/src/types.ts b/src/types.ts index aaf9d75d4..9983b3994 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3504,6 +3504,7 @@ export class ZodRecord< const pairs: { key: ParseReturnType; value: ParseReturnType; + alwaysSet: boolean; }[] = []; const keyType = this._def.keyType; @@ -3515,6 +3516,7 @@ export class ZodRecord< value: valueType._parse( new ParseInputLazyPath(ctx, ctx.data[key], ctx.path, key) ), + alwaysSet: key in ctx.data, }); }