KembaliBelajar Schema Validation Dengan Zod
Pendahuluan

Perbedaan Zod dan TypeScript

Sekilas, TypeScript dan Zod terlihat seperti menyelesaikan masalah yang sama. Padahal, keduanya bekerja pada lapisan yang berbeda dan justru saling melengkapi. Pada bab ini kita akan membahas perbedaannya agar peran masing-masing menjadi lebih jelas.

TypeScript Bekerja pada Tahap Kompilasi

TypeScript memeriksa tipe data pada saat kita menulis kode. Setelah dikompilasi menjadi JavaScript, semua anotasi tipe akan dihapus. Pada saat aplikasi berjalan di browser atau server, yang tersisa hanyalah JavaScript murni.

Mari perhatikan contoh berikut:

api-handler.ts
type User = {
  name: string;
  age: number;
};

async function getUser(): Promise<User> {
  const res = await fetch('/api/user');
  const data = await res.json();
  return data;
}

Sekilas terlihat aman, bukan? Function getUser dianotasikan dengan return type Promise<User>. Akan tetapi, sebenarnya tidak ada yang memeriksa apakah data benar-benar sebuah User. TypeScript hanya mempercayai anotasi tersebut. Apabila API tiba-tiba mengembalikan { name: 'Nauval', age: 'dua belas' }, kode kita akan tetap berjalan dan baru gagal di tempat lain ketika data tersebut digunakan.

Sebagai contoh, kita ingin menampilkan umur pengguna pada tahun depan:

penggunaan.ts
const user = await getUser();
const nextYear = user.age + 1;

console.log(`Tahun depan umur Anda ${nextYear}`);
// Output: "Tahun depan umur Anda dua belas1"

Tidak ada error yang dilempar. Akan tetapi, hasilnya sudah jelas salah, karena JavaScript melakukan string concatenation alih-alih operasi penjumlahan. Atau, kasus lain, ketika kita melakukan pengecekan:

pengecekan.ts
if (user.age >= 18) {
  console.log('Boleh akses');
}
// Tidak pernah masuk, karena 'dua belas' >= 18 menghasilkan false

Pengguna yang seharusnya boleh mengakses fitur tersebut, justru ditolak. Lagi-lagi tanpa error yang jelas. Bug seperti ini termasuk yang paling sulit dilacak, karena gejalanya muncul jauh dari sumber masalahnya.

Zod Bekerja pada Saat Runtime

Zod memeriksa tipe data pada saat kode berjalan. Kita menulis schema, lalu mem-parse data yang masuk. Apabila data tersebut tidak sesuai, Zod akan langsung melempar error pada saat itu juga.

api-handler.ts
import { z } from 'zod';

const userSchema = z.object({
  name: z.string(),
  age: z.number(),
});

async function getUser() {
  const res = await fetch('/api/user');
  const data = await res.json();
  return userSchema.parse(data);
}

Sekarang, apabila API mengembalikan data yang tidak valid, kita akan mendapatkan error yang jelas, di tempat yang jelas, dengan informasi yang detail.

Saling Melengkapi

Zod tidak menggantikan TypeScript. Keduanya saling melengkapi:

  • TypeScript memeriksa kode yang kita tulis
  • Zod memeriksa data yang masuk dari luar

Selain itu, kita dapat menurunkan tipe TypeScript langsung dari schema Zod melalui z.infer, sehingga tidak ada duplikasi:

infer.ts
import { z } from 'zod';

const userSchema = z.object({
  name: z.string(),
  age: z.number(),
});

type User = z.infer<typeof userSchema>;
// type User = { name: string; age: number }

function greet(user: User) {
  return `Halo, ${user.name}`;
}

Schema dan tipe selalu sinkron, karena keduanya berasal dari satu sumber. Apabila kita menambahkan field baru pada userSchema, tipe User akan ikut diperbarui secara otomatis.

Kapan Zod Dibutuhkan

Aturan praktisnya adalah setiap kali data berasal dari luar kendali kita, lakukan validasi menggunakan Zod. Beberapa contohnya:

  • Response dari API
  • Payload dari form atau request body
  • Query parameter dari URL
  • Data yang dimuat dengan JSON.parse dari localStorage
  • Environment variables
  • Fail yang diunggah pengguna

Untuk data internal yang sepenuhnya kita kendalikan, cukup gunakan TypeScript saja. Validasi menggunakan Zod tidak diperlukan, karena TypeScript sudah memadai pada konteks tersebut.

internal.ts
type Theme = 'dark' | 'light';

function nextTheme(current: Theme): Theme {
  return current === 'dark' ? 'light' : 'dark';
}

Tipe Theme di atas hanya memiliki dua kemungkinan nilai, dan keduanya dideklarasikan di dalam kode kita sendiri. TypeScript sudah cukup untuk memastikan parameter current selalu salah satu dari 'dark' atau 'light', tanpa perlu validasi tambahan.

Progres kursus

Sudah paham pelajaran ini?

Tandai selesai untuk menyimpan progresmu di kursus ini.

Diskusi

0 komentar

Belum ada komentar.

Mulai diskusi