reactjs - Cum să validezi un tip literal de șir folosind zod
Am acest Tip
export type PaymentType = 'CHECK' | 'DIRECT DEPOSIT' | 'MONEY ORDER';
Vreau să validez acest tip de șir literal în zod. În prezent, îl am ca șir, dar acela greșit nu este un șir. Nu știu ce să pun.
const schema = z.object({
paymentType: z.string() // I want to validate this field
});
Până acum, am încercat enumerări, șiruri și obiecte. Nu pot găsi răspunsul potrivit.
Răspuns #1
Am comentat că aceasta ar putea fi o duplicată, deoarece esența întrebării ar putea fi rezolvată cu z.literal, dar este puțin diferită. Doar pentru a ilustra ce poți face:
import { z } from 'zod';
const PaymentTypeSchema = z.union([
z.literal('CHECK'),
z.literal('DIRECT DEPOSIT'),
z.literal('MONEY ORDER'),
]);
type PaymentType = z.infer<typeof PaymentTypeSchema>;
const schema = z.object({
paymentType: PaymentTypeSchema,
});
O abordare mai simplă decât aceasta este să folosești ajutorul z.enum, care elimină o parte din codul de bază:
const PaymentTypeSchema = z.enum(["CHECK", "DIRECT DEPOSIT", "MONEY ORDER"]);
const schema = z.object({
paymentType: PaymentTypeSchema,
});
Alternativ, poți transforma PaymentType într-un enum și să folosești z.nativeEnum pentru a parse valorile astfel:
enum PaymentType {
Check = 'CHECK',
DirectDeposit = 'DIRECT DEPOSIT',
MoneyOrder = 'MONEY ORDER'
}
const PaymentTypeSchema = z.nativeEnum(PaymentType);
const schema = z.object({
paymentType: PaymentTypeSchema,
});
Răspuns #2
@Millenial2020 Am aterizat aici căutând altceva... și este puțin târziu...
Totuși, iată un răspuns, inclusiv cum să rezolvi problema: „tipul 'string' nu poate fi atribuit tipului 'PaymentType'” pe care îl menționezi într-un comentariu la cealaltă răspuns din acest fir:
Încearcă să folosești as const:
// note the 'as const'
export const PAYMENT_TYPES = ['CHECK', 'DIRECT DEPOSIT', 'MONEY ORDER'] as const
// works great
export const zPaymentType = z.enum(PAYMENT_TYPES)
// these types are all equivalent
export type PaymentType = 'CHECK' | 'DIRECT DEPOSIT' | 'MONEY ORDER'
export type PaymentType_TypeScript = (typeof PAYMENT_TYPES)[number]
export type PaymentType_Zod = z.infer<typeof zPaymentType>
Acesta se numește asertare const, adăugată în TypeScript 3.4: vezi notele de lansare pentru această caracteristică.
as const spune TypeScript că definiția array-ului tău este un tuplu literal readonly și că această informație suplimentară este ceea ce îți permite să lucrezi cu el folosind definiții de tip + z.enum() din zod.
Când definești un array de șiruri de caractere și nu oferi alte informații, TypeScript deduce un tip „extins” care cuprinde toate valorile. Dacă te gândești, trebuie să presupună că array-ul tău este de tip string[] deoarece ai libertatea să manipulezi array-ul și să modifici elementele sale în lucruri care nu sunt unul dintre 'CHECK', 'DIRECT DEPOSIT' sau 'MONEY ORDER'.
Cealaltă răspuns sugerează utilizarea enum, însă poți căuta articole despre motivul pentru care enum-urile TypeScript sunt „periculoase” sau „defecte”. Abordarea as const oferă o capacitate similară cu enum-urile într-un mod mai sigur din punct de vedere al tipurilor... ceea ce ajută, de asemenea, să explici de ce o bibliotecă de tipare de tip run-time de frunte, precum zod, a ales să numească această abordare tipul său oficial enum în locul celui încorporat în limbaj (pe care îl poți folosi cu z.nativeEnum()).
