UNPKG

zod

Version:

TypeScript-first schema declaration and validation library with static type inference

191 lines (140 loc) • 4.89 kB
import { expectTypeOf, test } from "vitest"; import * as z from "zod/mini"; test("assignability", () => { // $ZodString z.string() satisfies z.core.$ZodString; // $ZodNumber z.number() satisfies z.core.$ZodNumber; // $ZodBigInt z.bigint() satisfies z.core.$ZodBigInt; // $ZodBoolean z.boolean() satisfies z.core.$ZodBoolean; // $ZodDate z.date() satisfies z.core.$ZodDate; // $ZodSymbol z.symbol() satisfies z.core.$ZodSymbol; // $ZodUndefined z.undefined() satisfies z.core.$ZodUndefined; // $ZodNullable z.nullable(z.string()) satisfies z.core.$ZodNullable; // $ZodNull z.null() satisfies z.core.$ZodNull; // $ZodAny z.any() satisfies z.core.$ZodAny; // $ZodUnknown z.unknown() satisfies z.core.$ZodUnknown; // $ZodNever z.never() satisfies z.core.$ZodNever; // $ZodVoid z.void() satisfies z.core.$ZodVoid; // $ZodArray z.array(z.string()) satisfies z.core.$ZodArray; // $ZodObject z.object({ key: z.string() }) satisfies z.core.$ZodObject; // $ZodUnion z.union([z.string(), z.number()]) satisfies z.core.$ZodUnion; // $ZodIntersection z.intersection(z.string(), z.number()) satisfies z.core.$ZodIntersection; // $ZodTuple z.tuple([z.string(), z.number()]) satisfies z.core.$ZodTuple; // $ZodRecord z.record(z.string(), z.number()) satisfies z.core.$ZodRecord; // $ZodMap z.map(z.string(), z.number()) satisfies z.core.$ZodMap; // $ZodSet z.set(z.string()) satisfies z.core.$ZodSet; // $ZodLiteral z.literal("example") satisfies z.core.$ZodLiteral; // $ZodEnum z.enum(["a", "b", "c"]) satisfies z.core.$ZodEnum; // $ZodPromise z.promise(z.string()) satisfies z.core.$ZodPromise; // $ZodLazy const lazySchema = z.lazy(() => z.string()); lazySchema satisfies z.core.$ZodLazy; // $ZodOptional z.optional(z.string()) satisfies z.core.$ZodOptional; // $ZodDefault z._default(z.string(), "default") satisfies z.core.$ZodDefault; // $ZodTemplateLiteral z.templateLiteral([z.literal("a"), z.literal("b")]) satisfies z.core.$ZodTemplateLiteral; // $ZodCustom z.custom<string>((val) => typeof val === "string") satisfies z.core.$ZodCustom; // $ZodTransform z.transform((val) => val as string) satisfies z.core.$ZodTransform; // $ZodNonOptional z.nonoptional(z.optional(z.string())) satisfies z.core.$ZodNonOptional; // $ZodReadonly z.readonly(z.object({ key: z.string() })) satisfies z.core.$ZodReadonly; // $ZodNaN z.nan() satisfies z.core.$ZodNaN; // $ZodPipe z.pipe(z.unknown(), z.number()) satisfies z.core.$ZodPipe; // $ZodSuccess z.success(z.string()) satisfies z.core.$ZodSuccess; // $ZodCatch z.catch(z.string(), "fallback") satisfies z.core.$ZodCatch; // $ZodFile z.file() satisfies z.core.$ZodFile; }); test("toZod", () => { type Company = { id: string; name: string; webAddress: string | null; }; const CompanySchema = z.object({ id: z.string(), name: z.string(), webAddress: z.nullable(z.string()), }); const Company = z.toZod<Company>()(CompanySchema); expectTypeOf<z.output<typeof Company>>().toEqualTypeOf<Company>(); const CoreCompany = z.core.toZod<Company>()(CompanySchema); expectTypeOf<z.output<typeof CoreCompany>>().toEqualTypeOf<Company>(); const UtilCompany = z.core.util.toZod<Company>()(CompanySchema); expectTypeOf<z.output<typeof UtilCompany>>().toEqualTypeOf<Company>(); const Transformed = z.toZod<{ count: number }>()( z.object({ count: z.pipe( z.string(), z.transform((value) => value.length) ), }) ); expectTypeOf<z.input<typeof Transformed>>().toEqualTypeOf<{ count: string }>(); expectTypeOf<z.output<typeof Transformed>>().toEqualTypeOf<{ count: number }>(); z.toZod<Company>()( // @ts-expect-error missing optional keys still fail exact output matching z.object({ id: z.string(), name: z.string(), }) ); z.toZod<Company>()( // @ts-expect-error extra keys fail exact output matching z.object({ id: z.string(), name: z.string(), webAddress: z.nullable(z.string()), extra: z.string(), }) ); z.toZod<Company>()( // @ts-expect-error wrong property output fails matching z.object({ id: z.number(), name: z.string(), webAddress: z.nullable(z.string()), }) ); }); test("assignability with type narrowing", () => { type _RefinedSchema<T extends z.ZodMiniType<object> | z.ZodMiniUnion> = T extends z.ZodMiniUnion ? RefinedUnionSchema<T> // <-- Type instantiation is excessively deep and possibly infinite. : T extends z.ZodMiniType<object> ? RefinedTypeSchema<z.output<T>> // <-- Type instantiation is excessively deep and possibly infinite. : never; type RefinedTypeSchema<T extends object> = T; type RefinedUnionSchema<T extends z.ZodMiniUnion> = T; });