Zod Lanjutan: Fitur Advanced dan Arsitektural (Bagian 2)
Artikel ini merupakan lanjutan dari pembahasan Zod bagian pertama. Pada bagian ini, kita akan membahas fitur-fitur advanced, tipe yang jarang digunakan, serta pola arsitektural production-grade.
Jika bagian pertama fokus pada validasi yang umum digunakan sehari-hari, bagian ini akan membawa Anda ke level yang lebih dalam — termasuk penggunaan untuk library author, sistem kompleks, dan clean architecture.
Primitive Lanjutan (Rarely Used Types)
BigInt
z.bigint();
z.bigint().positive();
Digunakan ketika membutuhkan integer yang melebihi batas Number.MAX_SAFE_INTEGER.
Contoh penggunaan:
- Sistem finansial
- Cryptography
- Blockchain integration
Symbol
z.symbol();
Jarang digunakan dalam aplikasi umum, namun tetap tersedia untuk kebutuhan spesifik berbasis JavaScript runtime.
Undefined dan Null
z.undefined();
z.null();
Digunakan ketika ingin memastikan suatu field secara eksplisit harus undefined atau null.
Berguna dalam kontrak API yang sangat ketat.
Any, Unknown, dan Never
Any
z.any();
Menerima semua nilai tanpa validasi.
⚠ Tidak direkomendasikan kecuali benar-benar diperlukan.
Unknown
z.unknown();
Lebih aman dibanding any, karena TypeScript tetap memaksa Anda melakukan pengecekan sebelum digunakan.
Cocok digunakan di boundary layer seperti parsing external API.
Never
z.never();
Digunakan untuk memastikan suatu nilai tidak boleh ada.
Sering dipakai dalam discriminated union untuk memastikan exhaustive checking.
Tuple
Tuple digunakan untuk array dengan struktur dan panjang tetap.
z.tuple([
z.string(),
z.number(),
]);
Contoh valid:
["hello", 123]
Contoh tidak valid:
["hello"]
Berbeda dengan z.array(), tuple memiliki struktur tetap.
Set dan Map
Set
z.set(z.string());
Memvalidasi struktur Set<string>.
Map
z.map(z.string(), z.number());
Memvalidasi Map<string, number>.
Digunakan saat bekerja dengan struktur data ES6 secara eksplisit.
catch() vs default()
default
z.string().default("anonymous");
Digunakan jika value undefined.
catch
z.number().catch(0);
Digunakan jika terjadi validation error.
Perbedaan penting:
default()→ fallback jika value tidak adacatch()→ fallback jika validasi gagal
pipe()
Digunakan untuk chaining transform dengan validasi tambahan.
z.string()
.transform((val) => Number(val))
.pipe(z.number().min(1));
Pipeline ini memastikan hasil transform tetap divalidasi.
Lebih aman dibanding hanya menggunakan transform().
describe()
z.string().describe("User email address");
Digunakan untuk memberikan metadata pada schema.
Sangat berguna untuk:
- OpenAPI generator
- Dokumentasi otomatis
Global Error Map
z.setErrorMap((issue, ctx) => {
return { message: "Custom error message" };
});
Digunakan untuk mengganti pesan error secara global.
Cocok untuk:
- Internationalization (i18n)
- Standardisasi error response
Recursive Schema dengan z.lazy()
Digunakan untuk struktur recursive seperti tree.
const Category = z.object({
name: z.string(),
children: z.array(z.lazy(() => Category)),
});
Tanpa z.lazy(), schema tidak dapat mereferensikan dirinya sendiri.
Promise Schema
z.promise(z.string());
Digunakan untuk memvalidasi nilai dalam Promise.
Jarang digunakan dalam form, namun relevan dalam utility atau library.
Function Schema
Zod dapat memvalidasi signature function.
z.function()
.args(z.string())
.returns(z.number());
Digunakan untuk:
- Library internal
- Contract validation
- Utility wrapper
Boundary Layer Pattern (Production-Grade Usage)
Dalam sistem production, Zod sering digunakan pada boundary layer:
- Request validation
- Response validation
- Service input validation
- Environment variable validation
Contoh validasi environment variable:
const envSchema = z.object({
DATABASE_URL: z.string().url(),
PORT: z.string().transform(Number),
});
const env = envSchema.parse(process.env);
Dengan pendekatan ini, sistem menjadi fail-fast dan lebih aman.
Memahami Parse Pipeline Internal
Secara konseptual, Zod melakukan proses berikut:
- Preprocess (jika ada)
- Base type validation
- Constraint validation (min, max, dll)
- Refinement / superRefine
- Transform / pipe
- Return parsed output
Memahami pipeline ini penting untuk menghindari bug dalam chaining transform dan refinement.
Penutup
Bagian kedua ini melengkapi pembahasan sebelumnya dan membawa pemahaman Zod ke tingkat yang lebih dalam.
Jika bagian pertama membuat Anda produktif, bagian kedua ini membantu Anda menjadi arsitek yang memahami bagaimana Zod bekerja secara menyeluruh.
Dengan menguasai kedua bagian ini, Anda memiliki fondasi kuat untuk membangun sistem yang:
- Type-safe
- Konsisten
- Fail-fast
- Scalable dalam jangka panjang