Zod Lanjutan: Fitur Advanced dan Arsitektural (Bagian 2)
3 min read

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 ada
  • catch() → 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:

  1. Preprocess (jika ada)
  2. Base type validation
  3. Constraint validation (min, max, dll)
  4. Refinement / superRefine
  5. Transform / pipe
  6. 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