From 9148e0f7a7a5e7ed83c072850d46eb9cb77eea20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20N=C3=A9meth?= Date: Thu, 2 May 2024 17:17:01 +0200 Subject: [PATCH 1/3] docs: Corrected typo in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bc6dda3e8..da6d13406 100644 --- a/README.md +++ b/README.md @@ -2681,7 +2681,7 @@ Note that branded types do not affect the runtime result of `.parse`. It is a st This method returns a `ZodReadonly` schema instance that parses the input using the base schema, then calls `Object.freeze()` on the result. The inferred type is also marked as `readonly`. ```ts -const schema = z.object({ name: string }).readonly(); +const schema = z.object({ name: z.string() }).readonly(); type schema = z.infer; // Readonly<{name: string}> From df00938a65186c3a8e7b76ef0e96977bbd2cf494 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20N=C3=A9meth?= Date: Thu, 2 May 2024 17:17:15 +0200 Subject: [PATCH 2/3] test: result freezing after async parse --- src/__tests__/readonly.test.ts | 50 ++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/__tests__/readonly.test.ts b/src/__tests__/readonly.test.ts index 267ff190c..073bc533d 100644 --- a/src/__tests__/readonly.test.ts +++ b/src/__tests__/readonly.test.ts @@ -202,3 +202,53 @@ test("object freezing", () => { ) ).toBe(true); }); + +test("async object freezing", async () => { + expect( + Object.isFrozen(await z.array(z.string()).readonly().parseAsync(["a"])) + ).toBe(true); + expect( + Object.isFrozen( + await z.tuple([z.string(), z.number()]).readonly().parseAsync(["a", 1]) + ) + ).toBe(true); + expect( + Object.isFrozen( + await z + .map(z.string(), z.date()) + .readonly() + .parseAsync(new Map([["a", new Date()]])) + ) + ).toBe(true); + expect( + Object.isFrozen( + await z + .set(z.promise(z.string())) + .readonly() + .parseAsync(new Set([Promise.resolve("a")])) + ) + ).toBe(true); + expect( + Object.isFrozen( + await z.record(z.string()).readonly().parseAsync({ a: "b" }) + ) + ).toBe(true); + expect( + Object.isFrozen( + await z.record(z.string(), z.number()).readonly().parseAsync({ a: 1 }) + ) + ).toBe(true); + expect( + Object.isFrozen( + await z + .object({ a: z.string(), 1: z.number() }) + .readonly() + .parseAsync({ a: "b", 1: 2 }) + ) + ).toBe(true); + expect( + Object.isFrozen( + await z.promise(z.string()).readonly().parseAsync(Promise.resolve("a")) + ) + ).toBe(true); +}); From d06b4d6a02f3301ab3c651373c4a0ed86beebfb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20N=C3=A9meth?= Date: Thu, 2 May 2024 17:17:21 +0200 Subject: [PATCH 3/3] fix: result freezing after async parse --- src/types.ts | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/types.ts b/src/types.ts index 2aec55df2..a5217d4a2 100644 --- a/src/types.ts +++ b/src/types.ts @@ -5041,10 +5041,15 @@ export class ZodReadonly extends ZodType< > { _parse(input: ParseInput): ParseReturnType { const result = this._def.innerType._parse(input); - if (isValid(result)) { - result.value = Object.freeze(result.value); - } - return result; + const freeze = (data: ParseReturnType) => { + if (isValid(data)) { + data.value = Object.freeze(data.value); + } + return data; + }; + return isAsync(result) + ? result.then((data) => freeze(data)) + : freeze(result); } static create = (