javascript - Hur man får nycklarna i ett zod-schema
Jag har ett zod-objekt som är definierat så här:
const schema = z.object({
firstName: z.string().min(1, 'Required'),
middleName: z.string().optional(),
lastName: z.string().min(1, 'Required'),
phoneCountryCode: z.string().min(1, 'Required'),
phoneNumber: z.string().min(1, 'Required'),
countryOfResidence: z.string().min(1, 'Required'),
});
Hur kan jag extrahera nycklarna från ZodObject?
Självklart kan jag definiera ingångs-object först och sedan infoga det som ett argument för z.object
const schemaRawShape = {
firstName: z.string().min(1, 'Required'),
middleName: z.string().optional(),
lastName: z.string().min(1, 'Required'),
phoneCountryCode: z.string().min(1, 'Required'),
phoneNumber: z.string().min(1, 'Required'),
countryOfResidence: z.string().min(1, 'Required'),
} satisfies z.ZodRawShape
const schema = z.object(schemaRawShape);
const keys = Object.keys(infoStepSchemaCommonObj)
Men det blir svårare att läsa och följa när schemat blir mer komplicerat.
Till exempel när man hanterar unioner och/eller snitt.
Se diskussion på GitHub
REDIGERA :
Jag borde ha klargjort detta tidigare, men vi måste kunna extrahera nycklar från unioner, snitt och andra mer komplexa scheman.
Detta schema kommer inte att ha shape och därmed kommer koden att ge ett fel:
<script type="module">
import { z } from "https://esm.sh/[email ";
const schema1 = z.object({
firstName: z.string().min(1, "Required"),
middleName: z.string().optional(),
lastName: z.string().min(1, "Required"),
phoneCountryCode: z.string().min(1, "Required"),
phoneNumber: z.string().min(1, "Required"),
countryOfResidence: z.string().min(1, "Required"),
});
const schema2 = z.object({
more: z.string()
})
const schema = schema1.and(schema2)
const propertyNames = Object.keys(schema.shape);
console.log(propertyNames);
</script>Redigera - Fullt exempel med snitt och unioner
import { differenceInYears } from 'date-fns';
import * as z from 'zod';
const password = z
.string()
.min(10, 'Must be at least 10 characters long')
.regex(/\d/g, 'Must contain a number')
.regex(/[a-z]/g, 'Must contain a lower case character')
.regex(/[A-Z]/g, 'Must contain an upper case character')
.regex(/[^\w\d]/g, 'Must contain a special character');
const infoStepSchemaCommon = z.object({
firstName: z.string().min(1, 'Required'),
middleName: z.string().optional(),
lastName: z.string().min(1, 'Required'),
phoneCountryCode: z.string().min(1, 'Required'),
phoneNumber: z.string().min(1, 'Required'),
countryOfResidence: z.string().min(1, 'Required'),
});
const coerceNumber = z.coerce.number({
required_error: 'Required',
invalid_type_error: 'Must be a number',
});
const ageRestrictionString = 'Must be at least 12 years old';
const infoStepSchemaWithoutNationalId = z
.object({
hasNationalId: z.literal(false).optional(),
birthMonth: coerceNumber.min(1).max(12),
birthDay: coerceNumber.min(1).max(31, 'No month has more than 31 days'),
birthYear: coerceNumber.min(1900).max(new Date().getFullYear()),
})
.refine(
(d) =>
differenceInYears(
new Date(),
new Date(d.birthYear, d.birthMonth - 1, d.birthDay)
) >= 12,
{ message: ageRestrictionString, path: ['birthYear'] }
)
.and(infoStepSchemaCommon);
const infoStepSchemaWithNationalId = z
.object({
hasNationalId: z.literal(true),
nationalId: z
.string()
.min(1, 'Required')
.min(10, 'Must contain at least 10 digits')
.max(10, 'Must not contain more than 10 digits')
.regex(/^\d+$/, 'Must only contain numbers')
})
.and(infoStepSchemaCommon);
export const emailStepSchema = z.object({
email: z.string().min(1, 'Required').email(),
});
export const infoStepSchema = infoStepSchemaWithoutNationalId.or(
infoStepSchemaWithNationalId
);
export const passwordStepSchema = z
.object({
languageId: z.string(),
password,
passwordAgain: password,
privacyPolicyAccepted: z.coerce
.boolean()
.refine((v) => v, 'Must accept to continue'),
clubConditionsAccepted: z.coerce
.boolean()
.refine((v) => v, 'Must accept to continue'),
})
.refine((data) => data.password === data.passwordAgain, {
message: "Passwords don't match",
path: ['passwordAgain'],
});
export const signupFormSchema = emailStepSchema
.and(infoStepSchema)
.and(passwordStepSchema);
- Mål 1: Extrahera alla möjliga nycklar från
signupFormSchema - Mål 2: Extrahera alla möjliga nycklar från varje "steg"-schema
Det sagt, är jag faktiskt ganska nöjd med min nuvarande lösning som använder Proxy, men om det finns en mindre "hackig" metod så är jag helt för det.
Svar #1
I den senaste zod kan du få dem med keyof().options.
const keys = schema.keyof().options
Svar #2
Prova detta
schema.keyof()._def.values
