zod icon indicating copy to clipboard operation
zod copied to clipboard

ZodReadonly missing methods to manipulate schema shape

Open ravinggenius opened this issue 8 months ago • 1 comments

Several methods for manipulating the shape of a schema are conspicuously missing just by marking a schema as read-only:

import { z } from "zod";

export const EDITION = z.enum(["bedrock", "java"]);

export const VERSION = z.object({
	id: z.string().uuid(),
	createdAt: z.coerce.date(),
	updatedAt: z.coerce.date(),
	edition: EDITION,
	version: z.string(),
	cycle: z.tuple([z.number().nonnegative(), z.number().nonnegative()]),
	releasedOn: z.coerce.date(),
	releaseNotesUrl: z.string().url(),
	isPublished: z.boolean().default(false).optional()
});

export const LATEST_VERSION = VERSION.extend({
	isLatest: z.boolean(),
	isLatestInCycle: z.boolean()
}).readonly();

export const RARITY = z.enum(["common", "uncommon", "rare", "epic"]);

export const ITEM = z.object({
	id: z.string().uuid(),
	createdAt: z.coerce.date(),
	updatedAt: z.coerce.date(),
	identity: z.string(),
	wikiUrl: z.string().url(),
	rarity: RARITY.default("common").optional(),
	stackSize: z.number().positive().default(64).optional(),
	isRenewable: z.boolean()
});

export const VERSIONED_ITEM = ITEM.and(
	z.object({
		// unrelated, but if there's a better way to rename a property, i'd like to know
		versionId: LATEST_VERSION.shape.id // .shape isn't available because LATEST_VERSION is read-only
	})
)
	.and(
		LATEST_VERSION.pick({ // .pick() isn't available because LATEST_VERSION is read-only
			edition: true,
			version: true,
			cycle: true,
			isLatest: true,
			isLatestInCycle: true
		})
	)
	.readonly();

Everything is fine if I remove .readonly() from LATEST_VERSION and VERSIONED_ITEM. However these schemas represent views in the database, so they are inherently read-only. Shouldn't we be able to mark schemas as read-only and still be able to use helpers like .pick(), .omit() and .shape?


Edit: formatting

ravinggenius avatar Jun 15 '24 21:06 ravinggenius