Menentukan Skema Zod yang Kompleks
Pelajari cara membuat skema Zod tingkat lanjut untuk objek, larik, dan aturan validasi khusus.
Menentukan Skema Zod yang Kompleks adalah pelajaran tRPC End-to-End Type Safe APIs gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar tRPC End-to-End Type Safe APIs, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus tRPC End-to-End Type Safe APIs mencakup 4 pelajaran total.
Bagian dari pelajaran ini belum diterjemahkan dan ditampilkan dalam bahasa Inggris.
Beyond Basic Zod Types
Welcome back! In the previous lesson, we learned about Zod's basic types like string, number, and boolean. These are great for simple validations.
But real-world data is rarely simple! We often deal with complex structures like user profiles, product lists, or nested configurations.
Today, we'll dive into defining schemas for these more intricate data types, making your tRPC APIs even more robust.
Crafting Object Schemas
The z.object() method is your go-to for validating JavaScript objects. You define each property's schema within it.
- Each key in the object corresponds to a property in your data.
- The value for each key is another Zod schema, defining that property's type and rules.
- By default, all properties defined in
z.object()are required.
Let's see how to define a schema for a simple user object:
import { z } from 'zod';
const UserProfileSchema = z.object({
username: z.string().min(3),
email: z.string().email(),
age: z.number().int().positive()
});Running an Object Schema
To validate data against an object schema, you use the .parse() method. If the data doesn't match, it throws a ZodError.
Try running this example to see valid and invalid object data in action!
import { z } from 'zod';
const UserProfileSchema = z.object({
username: z.string().min(3, "Username must be at least 3 chars"),
email: z.string().email("Invalid email format"),
age: z.number().int().positive("Age must be a positive integer")
});
function validateUser(userData: unknown) {
try {
const parsedUser = UserProfileSchema.parse(userData);
console.log("Validation Success:", JSON.stringify(parsedUser));
} catch (error: any) {
console.log("Validation Error:", error.issues[0].message);
}
}
console.log("--- Valid User ---");
validateUser({
username: "coderKid",
email: "kid@example.com",
age: 12
});
console.log("\n--- Invalid User (Age) ---");
validateUser({
username: "coderKid",
email: "kid@example.com",
age: -5
});Nesting Objects for Complexity
Applications often have data that's structured in a hierarchical way. Zod handles this beautifully by allowing you to nest object schemas.
You can define an object schema, and then use it as the type for a property within another object schema. This keeps your schemas organized and reusable.
Here's how you might define a ShippingAddress schema and nest it within a OrderSchema:
import { z } from 'zod';
const ShippingAddressSchema = z.object({
street: z.string().min(5),
city: z.string().min(2),
zipCode: z.string().regex(/^\d{5}(-\d{4})?$/)
});
const OrderSchema = z.object({
orderId: z.string().uuid(),
items: z.array(z.string()), // Array of item IDs
address: ShippingAddressSchema // Nested object!
});Working with Array Schemas
When you need to validate a list of items, z.array() comes to the rescue. It takes another Zod schema as its argument, defining the type of each element in the array.
You can validate arrays of basic types (like strings or numbers) or even arrays of complex objects.
z.array(z.string()): An array where every element must be a string.z.array(z.object({...})): An array where every element must conform to a specific object schema.
import { z } from 'zod';
const TagSchema = z.string().min(2).max(20);
const TagsArraySchema = z.array(TagSchema).min(1).max(5);
const ProductSchema = z.object({
id: z.string().uuid(),
name: z.string().min(3),
price: z.number().positive(),
tags: TagsArraySchema // Array of strings (tags)
});Runnable Array Schema Example
Let's put z.array() to the test. This example defines a schema for an array of numbers and then tries to validate both a valid and an invalid array.
Notice how you can chain methods like .min() and .max() directly onto the array schema itself to enforce array length constraints.
import { z } from 'zod';
const NumberListSchema = z.array(z.number()).min(2, "Must have at least 2 numbers").max(5, "Cannot have more than 5 numbers");
function validateNumberList(listData: unknown) {
try {
const parsedList = NumberListSchema.parse(listData);
console.log("Validation Success:", JSON.stringify(parsedList));
} catch (error: any) {
console.log("Validation Error:", error.issues[0].message);
}
}
console.log("--- Valid List ---");
validateNumberList([10, 20, 30]);
console.log("\n--- Invalid List (Too Short) ---");
validateNumberList([5]);
console.log("\n--- Invalid List (Wrong Type) ---");
validateNumberList([1, "two", 3]);Unions and Enums for Choices
Sometimes, a property can have one of several possible types or values. Zod provides z.union() and z.enum() for these scenarios.
z.union([schema1, schema2]): Allows a value to match any one of the provided schemas. E.g., a status could be astringor anumber.z.enum(['val1', 'val2']): Restricts a string value to be one of a predefined set of literal strings. This is perfect for fixed categories or states.
import { z } from 'zod';
const IDSchema = z.union([z.string().uuid(), z.number().int().positive()]);
const StatusEnum = z.enum(['pending', 'processing', 'completed', 'failed']);
const TaskSchema = z.object({
taskId: IDSchema, // Could be UUID string or positive integer
description: z.string(),
status: StatusEnum // Must be one of 'pending', 'processing', etc.
});Custom Validation with .refine()
Zod's built-in validators cover many cases, but what if you have a unique rule? The .refine() method lets you add custom validation logic to any schema.
It takes two arguments:
- A predicate function that returns
truefor valid data,falseotherwise. - An error message string or an object with a custom message.
.refine() runs after all other schema validations, so you can be sure the data has the correct basic type and structure first.
import { z } from 'zod';
const PasswordSchema = z.string()
.min(8, "Password must be at least 8 characters long")
.refine(password => /[A-Z]/.test(password), "Password must contain at least one uppercase letter")
.refine(password => /[0-9]/.test(password), "Password must contain at least one number");
const UserLoginSchema = z.object({
email: z.string().email(),
password: PasswordSchema
});Running Custom Refine Example
Let's test a schema with a custom .refine() rule. We'll ensure a given date string is in the future.
This shows how powerful .refine() can be for enforcing business logic that isn't covered by standard type checks.
import { z } from 'zod';
const FutureDateSchema = z.string().datetime()
.refine(
(dateString) => new Date(dateString) > new Date(),
"Date must be in the future"
);
function validateFutureDate(dateInput: unknown) {
try {
const parsedDate = FutureDateSchema.parse(dateInput);
console.log("Validation Success:", parsedDate);
} catch (error: any) {
console.log("Validation Error:", error.issues[0].message);
}
}
console.log("--- Valid Future Date ---");
const future = new Date();
future.setDate(future.getDate() + 1);
validateFutureDate(future.toISOString());
console.log("\n--- Invalid Past Date ---");
const past = new Date();
past.setDate(past.getDate() - 1);
validateFutureDate(past.toISOString());Optional Properties & Defaults
Not every property in an object is always required. Zod helps you mark properties as optional and even provide default values.
.optional(): Makes a property optional. If it's missing, Zod won't throw an error..nullable(): Allows a property to benull..default(value): Provides a fallback value if the property is missing orundefined.
Using these can make your schemas more flexible and handle partial data gracefully.
import { z } from 'zod';
const UserSettingsSchema = z.object({
theme: z.enum(['light', 'dark']).default('light'), // Default to 'light'
notifications: z.boolean().optional(), // Optional boolean
bio: z.string().max(200).nullable().optional() // Optional, can be null
});Quick Check on Zod Schemas
You've learned how to define object and array schemas, use unions/enums, and even add custom validation. Which of the following statements about Zod's complex schemas is TRUE?
Recap: Mastering Complex Schemas
Great job! You've taken a significant leap in your ability to define robust data validations with Zod.
We covered:
z.object()for structured data, including nesting.z.array()for lists of items.z.union()andz.enum()for handling multiple possible types or predefined values..refine()for powerful custom validation rules.- Making properties optional, nullable, and setting defaults.
These tools are essential for building secure and predictable tRPC APIs. Next, we'll integrate these Zod schemas directly into your tRPC procedures!
Belajar tRPC End-to-End Type Safe APIs dengan tutor AI — gratis
Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.
- Kursus
- 10
- Pelajaran
- 40
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Menentukan Skema Zod yang Kompleks” gratis?
Ya — teks lengkap “Menentukan Skema Zod yang Kompleks” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus tRPC End-to-End Type Safe APIs, upgrade ke CoddyKit PRO. Kursus tRPC End-to-End Type Safe APIs mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Menentukan Skema Zod yang Kompleks”?
Pelajari cara membuat skema Zod tingkat lanjut untuk objek, larik, dan aturan validasi khusus. Kamu berlatih tRPC End-to-End Type Safe APIs dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai tRPC End-to-End Type Safe APIs?
Tidak diperlukan pengalaman sebelumnya. tRPC End-to-End Type Safe APIs di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.
Berapa lama pelajaran “Menentukan Skema Zod yang Kompleks” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran tRPC End-to-End Type Safe APIs ini?
Ya. Setiap pelajaran tRPC End-to-End Type Safe APIs menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Pengantar Skema Zod
- Menentukan Skema Zod yang Kompleks
- Mengintegrasikan Zod dalam Prosedur tRPC
- Mentransformasi dan Menyempurnakan Data Zod