Tidak suka iklan? Pergi Bebas Iklan Hari ini

JSON ke TypeScript Buat Interface Otomatis dari Respons API

Diperbarui pada

Menghasilkan antarmuka TypeScript secara manual untuk setiap respons API sangat melelahkan dan rentan kesalahan. Pelajari cara menghasilkan antarmuka secara otomatis dari data JSON aktual, lalu tambahkan validasi di runtime dengan Zod — karena tipe data hilang saat di runtime dan `any` bukan solusi.

JSON ke TypeScript: Menghasilkan Interface dari Respons API 1
IKLAN · HAPUS?

Anda baru saja mengambil data dari API pihak ketiga. Responsnya adalah blok JSON yang padat — objek bersarang, array, dan field yang bisa nol — dan sekarang Anda harus menentukan cara mengetiknya dalam TypeScript. Maka Anda membuka file baru, mulai mengetik interface User { ... }, dan 20 menit kemudian Anda mendapatkan sesuatu yang mungkin sesuai dengan data sebenarnya. Mungkin saja.

Ada cara yang lebih baik. Alat yang mengonversi JSON langsung ke interface TypeScript mengurangi tugas 20 menit tersebut menjadi detik. Artikel ini menjelaskan bagaimana tipe yang dihasilkan terlihat, bagaimana menangani kasus yang tidak biasa (nol, gabungan, peningkatan mendalam), dan mengapa Anda harus menggabungkan tipe yang dihasilkan dengan skema Zod untuk menangkap ketidaksesuaian bentuk di runtime — bukan hanya di waktu kompilasi.

Mengapa Interface TypeScript untuk Respons API Penting

Proposisi TypeScript adalah menangkap kesalahan sebelum kode Anda dijalankan. Tanpa respons API yang diberi tipe, Anda berjalan tanpa panduan: mengakses properti yang mungkin tidak ada, menganggap nilai opsional sebagai wajib, atau secara diam-diam mengubah string "null" menjadi sesuatu yang tidak diharapkan di bagian selanjutnya.

Pertimbangkan skenario umum ini:

const user = await fetchUser(id);
console.log(user.address.city); // TypeError at runtime if address is null

Jika Anda telah mengetikkan respons dengan benar — dengan address: Address | null — TypeScript akan langsung menandai akses tersebut. Komplier adalah pertahanan pertama Anda, tetapi hanya jika Anda memberikan sesuatu yang bisa digunakan olehnya.

Menulis interface secara manual untuk setiap API adalah pekerjaan yang membosankan dan rentan terhadap kesalahan. Anda salah baca skema, melewatkan field opsional, atau menyalin versi yang sudah usang. Membangkitkan interface langsung dari data JSON yang nyata menghilangkan kesalahan manusia dari proses tersebut.

Apa yang Dihasilkan oleh Konversi JSON ke TypeScript

Ambil respons API yang sederhana:

{
  "id": 42,
  "username": "jsmith",
  "email": "j@example.com",
  "createdAt": "2024-01-15T10:30:00Z",
  "role": "admin",
  "profile": {
    "bio": "Developer",
    "avatar": null
  }
}

Tempelkan ke dalam Generator Antarmuka TypeScript ke JSON dan Anda mendapatkan:

interface Profile {
  bio: string;
  avatar: null;
}

interface RootObject {
  id: number;
  username: string;
  email: string;
  createdAt: string;
  role: string;
  profile: Profile;
}

Beberapa hal yang perlu diperhatikan:

  • Objek bersarang menjadi interface yang terpisahProfile dikonversi secara otomatis daripada dimasukkan langsung.
  • Tanggal diwakili sebagai string — JSON tidak memiliki tipe tanggal, sehingga string ISO tetap sebagai string. Anda perlu memarsingkannya secara manual.
  • avatar: null diwakili sebagai literal null — yang akurat tetapi tidak lengkap. Lebih banyak tentang hal ini di bawah ini.

Menangani Kasus yang Sulit

Field yang Bisa Nol

Ketika sebuah field adalah null dalam JSON contoh Anda, generator mengetiknya sebagai null. Namun dalam praktiknya, field tersebut kemungkinan besar bervariasi antara nilai nyata dan null tergantung pada data. Anda ingin menyesuaikannya secara manual:

// Generated
avatar: null;

// What you actually want
avatar: string | null;

Hal yang sama berlaku untuk field opsional yang ternyata terisi dalam contoh Anda — tambahkan ? ke properti apa pun yang mungkin tidak ada dalam beberapa respons.

Susunan

Array dari objek ditangani secara bersih. Diberikan:

{
  "posts": [
    { "id": 1, "title": "Hello", "published": true },
    { "id": 2, "title": "World", "published": false }
  ]
}

Generator menghasilkan:

interface Post {
  id: number;
  title: string;
  published: boolean;
}

interface RootObject {
  posts: Post[];
}

Tipe Gabungan

Jika contoh JSON Anda menunjukkan field yang mengandung tipe berbeda di berbagai catatan — misalnya, sebuah value yang bisa menjadi angka atau string — Anda harus mewakilinya sebagai gabungan. Tipe yang dihasilkan tidak akan menangkap ini dari satu contoh, sehingga penting untuk memeriksa terhadap dokumentasi API Anda:

value: string | number;

Penyimpanan yang Sangat Mendalam

Penyimpanan mendalam adalah tempat di mana pengetikan manual benar-benar runtuh — dan tempat di mana generator memperoleh nilai. Respons dengan tiga atau empat level penyimpanan dipecahkan menjadi hierarki bersih dari interface yang bernama, masing-masing bertanggung jawab atas bentuknya sendiri.

Kecuali antara Tipe di Waktu Kompilasi dan Realitas di Runtime

Ini adalah hal yang sering diabaikan oleh pengguna TypeScript baru: tipe hilang di runtime. TypeScript dikompilasi ke JavaScript, dan JavaScript tidak memiliki konsep interface. Jika API Anda mengembalikan bentuk yang tidak sesuai dengan tipe yang dideklarasikan, TypeScript tidak akan tahu — dan tidak akan memberi tahu Anda.

Ini membuat pola umum penggunaan casting respons API benar-benar berbahaya:

const data = await response.json() as User; // No validation, just trust

Penggunaan casting ini mengatakan kepada TypeScript “percayalah, ini adalah User” — tetapi TypeScript tidak memiliki cara untuk memverifikasinya. Jika API berubah bentuknya atau mengembalikan objek kesalahan, kode Anda akan rusak di runtime dalam cara yang tidak pernah diingatkan oleh kompiler.

Solusinya adalah validasi di runtime.

Zod untuk Validasi di Runtime

Zod adalah library validasi skema yang pertama kali dirancang untuk TypeScript. Anda mendefinisikan skema sekali, menggunakan skema tersebut untuk memarsing data yang masuk, dan mendapatkan nilai yang sepenuhnya diberi tipe — atau kesalahan rinci jika bentuknya tidak sesuai. Tidak ada casting, tidak ada tebakan.

Menggunakan contoh JSON yang sama dari sebelumnya, skema Generator Skema Zod dari JSON menghasilkan:

import { z } from "zod";

const ProfileSchema = z.object({
  bio: z.string(),
  avatar: z.null(),
});

const RootObjectSchema = z.object({
  id: z.number(),
  username: z.string(),
  email: z.string(),
  createdAt: z.string(),
  role: z.string(),
  profile: ProfileSchema,
});

type RootObject = z.infer<typeof RootObjectSchema>;

Perhatikan baris terakhir: z.infer mengambil tipe TypeScript secara langsung dari skema. Anda mendapatkan keamanan tipe di waktu kompilasi dan validasi di runtime dari satu sumber kebenaran.

Penggunaannya di batas fetch terlihat seperti ini:

const rawData = await response.json();
const user = RootObjectSchema.parse(rawData); // throws if shape is wrong

// Or use safeParse to avoid throwing:
const result = RootObjectSchema.safeParse(rawData);
if (!result.success) {
  console.error(result.error.issues);
} else {
  console.log(result.data.username); // fully typed
}

Sesuaikan skema yang dihasilkan untuk menangani kasus yang tidak nol yang tidak dapat ditebak oleh generator dari satu contoh:

avatar: z.string().nullable(), // was z.null()
bio: z.string().optional(),    // if the field might be absent

interface vs type: Mana yang Harus Anda Gunakan?

Kedua-duanya interface dan type alias dapat mewakili bentuk objek dalam TypeScript, dan untuk kebanyakan pengetikan respons API mereka dapat diganti. Perbedaan praktis:

  • Interface dapat diperluas dan digabungkan — berguna jika Anda ingin memperluas tipe dasar di berbagai file. Penggabungan deklarasi memungkinkan Anda menambahkan field ke interface yang didefinisikan di tempat lain.
  • Type alias lebih fleksibel — mereka dapat mewakili gabungan, irisan, tuple, dan type terpeta, yang tidak bisa dilakukan oleh interface.
  • Pesan kesalahan cenderung lebih jelas dengan interface — TypeScript memperluas type alias dalam output kesalahan, yang dapat membuat kesalahan yang sangat dalam lebih sulit dibaca.

Untuk bentuk respons API, keduanya bekerja. Pilih interface jika Anda memperkirakan akan memperluas tipe; gunakan type jika Anda membutuhkan semantik gabungan atau irisan. Konsistensi dalam kodebase lebih penting daripada memilih salah satu.

Alur Praktis

Berikut adalah alur yang mengambil waktu menit bukan setengah hari:

  1. Ambil respons yang nyata. Gunakan tab jaringan browser Anda, Postman, atau curl untuk menangkap respons API yang nyata. Semakin lengkap contoh tersebut, semakin baik tipe yang dihasilkan.
  2. Buat interface TypeScript. Tempelkan JSON ke dalam Generator Antarmuka TypeScript ke JSON. Salin hasilnya ke dalam proyek Anda.
  3. Buat skema Zod. Tempelkan JSON yang sama ke dalam Generator Skema Zod dari JSON. Salin hasilnya ke dalam proyek Anda juga.
  4. Uraikan untuk field yang mungkin tidak ada atau diwakili sebagai literal atau field yang bisa hilang. Perbarui mereka menjadi null Validasi di batas fetch. string | null, .nullable(), atau .optional() sesuai kebutuhan.
  5. Ganti semua casting dengan as YourType . Sekarang tipe tersebut dijamin sesuai, bukan hanya diasumsikan. YourSchema.parse() atau safeParse()Itu adalah lingkaran penuh — dari JSON mentah ke keamanan kompilasi dan jaminan runtime dalam beberapa menit.

JSON ke TypeScript: Otomatisasi Interface dari Respons API 2

Ingin bebas iklan? Bebas Iklan Hari Ini

Instal Ekstensi Kami

Tambahkan alat IO ke browser favorit Anda untuk akses instan dan pencarian lebih cepat

Ke Ekstensi Chrome Ke Ekstensi Tepi Ke Ekstensi Firefox Ke Ekstensi Opera

Papan Skor Telah Tiba!

Papan Skor adalah cara yang menyenangkan untuk melacak permainan Anda, semua data disimpan di browser Anda. Lebih banyak fitur akan segera hadir!

IKLAN · HAPUS?
IKLAN · HAPUS?
IKLAN · HAPUS?

Pojok Berita dengan Sorotan Teknologi

Terlibat

Bantu kami untuk terus menyediakan alat gratis yang berharga

Belikan aku kopi
IKLAN · HAPUS?