Antarmuka TypeScript vs Tipe: Perbedaan Nyata, Diuji Dengan Kompiler

  1. Beranda
  2. Blog
  3. Pengembangan Perangkat Lunak

Pengembangan Perangkat Lunak

Antarmuka TypeScript vs Tipe: Perbedaan Nyata, Diuji Dengan Kompiler

Antarmuka dan alias tipe saling tumpang tindih sehingga pilihannya sering kali terasa sewenang-wenang. Inilah yang masing-masing dapat lakukan namun tidak dapat dilakukan oleh yang lain, yang dikonfirmasi oleh kesalahan kompiler nyata, ditambah aturan sederhana yang dapat diikuti oleh tim Anda.

8 menit baca
Antarmuka TypeScript vs tipe: perbedaan nyata, diuji dengan kompiler

Poin penting

  • Untuk bentuk objek biasa, antarmuka dan tipe alias hampir dapat dipertukarkan.
  • Hanya type yang dapat memberi nama gabungan, tupel, dan tipe non-objek lainnya.
  • Hanya interface yang mendukung penggabungan deklarasi, yang mana dua deklarasi digabungkan.
  • Aturan umum: antarmuka untuk bentuk objek, type untuk yang lainnya, diterapkan secara konsisten.

Beberapa pertanyaan TypeScript menimbulkan perdebatan sebanyak antarmuka TypeScript vs tipe. Banyak artikel mencantumkan perbedaan yang dulunya penting di versi lama tetapi sekarang sudah ketinggalan zaman. Jadi, daripada mengulangi klaim, kami mengujinya.

Kami menulis satu file untuk menguji setiap perbedaan, dan memeriksanya dengan TypeScript 5.6.3 dalam mode ketat. Kesalahan kompiler yang dikutip di bawah ini berasal dari proses tersebut. Perilaku dapat berubah antar versi, jadi periksalah versi TypeScript yang digunakan proyek Anda. Jika Anda baru mengenal bahasa ini, mulailah dengan Tutorial TypeScript untuk pemula kami.

Jawaban singkatnya

interface mendeskripsikan bentuk suatu objek, dan dapat diperluas atau dibuka kembali. Alias ​​​​type memberi nama pada tipe apa saja, termasuk objek, gabungan, tupel, dan tipe fungsi. Jika keduanya bisa berfungsi, perbedaannya sebagian besar terletak pada gaya.

Dimana mereka sama

Kedua deklarasi ini mendeskripsikan bentuk yang identik:

interface User {
  id: number;
  name: string;
  email?: string;
}

type UserAlias = {
  id: number;
  name: string;
  email?: string;
};

const a: User = { id: 1, name: "Asha" };
const b: UserAlias = a;   // no error

TypeScript menggunakan pengetikan struktural, yang berarti membandingkan bentuk, bukan nama. Itu sebabnya User dapat ditugaskan ke UserAlias tanpa keluhan. Keduanya mendukung properti opsional, properti readonly, metode, dan tanda tangan indeks.

Antarmuka vs tipe berdampingan

Fitur antarmuka mengetik
Bentuk objek Ya Ya
Serikat pekerja, seperti "a" | "b" Tidak Ya
Tupel dan primitif Tidak Ya
Tipe yang dipetakan dan bersyarat Tidak Ya
Penggabungan deklarasi Ya Tidak, ini adalah kesalahan
Memperluas meluas & persimpangan
Sifat-sifat yang bertentangan Kesalahan pada deklarasi Diam-diam bisa menjadi never
Digunakan dengan implements Ya Ya, jika itu adalah tipe objek

Apa yang hanya bisa dilakukan oleh tipe

Banyak tipe berguna yang bukan merupakan bentuk objek sama sekali, dan hanya alias tipe yang dapat menamainya:

type Status = "pending" | "paid" | "shipped";   // union
type Point = [number, number];                    // tuple
type Handler = (event: string) => void;           // function type
type Keys = keyof User;                           // computed type
type ReadonlyUser = Readonly<User>;               // utility type

Tipe gabungan adalah salah satu fitur TypeScript yang paling berharga, karena kompiler kemudian menolak nilai apa pun di luar daftar:

let s: Status = "paid";
s = "refunded";

// error TS2322: Type '"refunded"' is not assignable to type 'Status'.

Ini menangkap kesalahan ketik dan nilai-nilai usang pada waktu kompilasi, sebelum mencapai produksi.

Penggabungan deklarasi

Jika Anda mendeklarasikan antarmuka dengan nama yang sama dua kali, TypeScript menggabungkannya menjadi satu:

interface Settings {
  theme: string;
}
interface Settings {
  language: string;
}

const settings: Settings = { theme: "dark", language: "en" };   // no error

Coba hal yang sama dengan alias tipe, dan kompiler menolak:

type Config = { theme: string };
type Config = { language: string };

// error TS2300: Duplicate identifier 'Config'.

Penggabungan adalah cara perpustakaan memungkinkan Anda memperluas tipenya. Misalnya, Anda dapat menambahkan properti khusus ke antarmuka global Window, atau ke objek permintaan kerangka kerja, tanpa mengubah pustaka. Itu sungguh berguna.

Sisi sebaliknya adalah penggabungan bisa terjadi secara tidak sengaja. Jika dua file dalam sebuah proyek mendeklarasikan antarmuka dengan nama yang sama dalam cakupan yang sama, keduanya digabungkan secara diam-diam, yang dapat membingungkan. Alias ​​tipe membuat tabrakan itu menjadi kesalahan.

memanjang vs persimpangan

Keduanya memungkinkan Anda membangun tipe yang sudah ada:

interface Admin extends User {
  permissions: string[];
}

type AdminAlias = UserAlias & { permissions: string[] };

Untuk properti yang kompatibel, hasilnya sama. Perbedaannya muncul dengan konflik. Ketika sebuah antarmuka mencoba mengubah tipe properti secara tidak kompatibel, kompilator segera melaporkannya:

interface Base { id: number }
interface Broken extends Base { id: string }

// error TS2430: Interface 'Broken' incorrectly extends interface 'Base'.
//   Types of property 'id' are incompatible.
//     Type 'string' is not assignable to type 'number'.

Sebuah persimpangan tidak mengeluh ketika diumumkan. Sebaliknya, properti yang bertentangan menjadi never, sebuah tipe yang tidak memiliki nilai apa pun. Kesalahan hanya muncul kemudian, ketika Anda mencoba menggunakannya:

type Mixed = { id: number } & { id: string };
const m: Mixed = { id: 1 };

// error TS2322: Type 'number' is not assignable to type 'never'.

Kesalahan berikutnya lebih membingungkan karena menunjukkan kesalahan yang sebenarnya. Ini adalah salah satu alasan praktis untuk memilih extends ketika membangun tipe objek.

Kelas dan implementasinya

Sebuah kelas bisa berjanji untuk mencocokkan bentuk menggunakan implements, dan ini berfungsi dengan antarmuka atau alias tipe objek:

class Account implements User {
  constructor(public id: number, public name: string) {}
}

Ini dikompilasi tanpa kesalahan. Perhatikan bahwa implements hanya memeriksa apakah kelasnya cocok. Itu tidak menambahkan properti atau kode apa pun. Sebuah kelas tidak dapat mengimplementasikan tipe gabungan, karena tidak ada satu bentuk pun yang cocok.

Tipe readonly dan utilitas

Jenis utilitas seperti Readonly, Partial, Pick dan Omit berfungsi dengan antarmuka dan alias. Hasilnya adalah tipe baru, yang biasanya diberi nama dengan alias tipe:

const r: ReadonlyUser = { id: 3, name: "Dev" };
r.name = "Chitra";

// error TS2540: Cannot assign to 'name' because it is a read-only property.

Ingatlah bahwa readonly hanya merupakan pemeriksaan waktu kompilasi. Saat dijalankan, objeknya adalah JavaScript biasa, dan masih dapat diubah dengan kode yang melewati tipe tersebut.

Kiat: Tipe menghilang saat TypeScript dikompilasi ke JavaScript. Data yang datang dari luar, seperti respons API, tidak diperiksa pada saat dijalankan hanya karena memiliki tipe. Validasi, misalnya dengan perpustakaan skema. Tutorial Pengambilan API kami mencakup penanganan respons API dengan aman.

Kinerja kompiler

Panduan kinerja tim TypeScript sendiri menyarankan untuk memilih antarmuka yang menggunakan extends daripada persimpangan besar, karena kompiler dapat menyimpan hubungan antarmuka dalam cache dengan lebih efisien. Dalam proyek kecil dan menengah, Anda tidak akan melihat perbedaan apa pun. Ini mungkin penting dalam basis kode yang sangat besar dengan tipe yang sangat tersusun. Kami tidak mengukurnya sendiri.

Mana yang harus Anda gunakan?

Aturan yang banyak digunakan, sejalan dengan panduan dari buku pegangan TypeScript, adalah:

  • Gunakan interface untuk bentuk objek, terutama API publik dan apa pun yang diimplementasikan oleh kelas atau yang lain dapat diperluas.
  • Gunakan type untuk gabungan, tupel, tipe fungsi, dan tipe yang dipetakan atau dihitung.
Anda mendefinisikan Gunakan
Model data, seperti Pengguna atau Pesanan antarmuka
Satu set nilai yang diizinkan type persatuan
Sepasang atau tripel dengan panjang tetap type tupel
Tanda tangan panggilan balik mengetik
Memperluas tipe perpustakaan interface, melalui penggabungan
Variasi dari tipe yang sudah ada type dengan tipe utilitas

Beberapa tim cukup menggunakan type di mana saja, dan itu juga berfungsi dengan baik. Yang paling penting adalah konsistensi, jadi pilihlah konvensi, tuliskan dalam panduan gaya Anda dan biarkan linter menerapkannya. Aturan ESLint consistent-type-definitions dari TypeScript-eslint dapat melakukan ini.

Kesalahan umum

  • Perdebatan tanpa akhir. Keduanya baik-baik saja untuk objek, jadi selesaikan aturannya sekali dan lanjutkan.
  • Penggabungan yang tidak disengaja. Menggunakan kembali nama antarmuka dalam cakupan yang sama menggabungkannya secara diam-diam.
  • Persimpangan yang bertentangan. Mereka membuat tipe never dengan kesalahan yang membingungkan nantinya.
  • Jenis yang dipercaya pada waktu proses. Tipe tersebut akan terhapus, jadi validasi data eksternal.
  • Menggunakan any untuk membungkam kesalahan. Ini mematikan pemeriksaan. Pilih unknown dan persempit.

Beralih di antara keduanya dalam basis kode yang sudah ada

Mengubah interface menjadi type, atau sebaliknya, biasanya aman untuk bentuk objek biasa, karena TypeScript membandingkan tipe berdasarkan strukturnya, bukan berdasarkan namanya. Beberapa hal yang masih perlu diperiksa sebelum Anda beralih:

  • Mengonversi antarmuka ke alias tipe menghilangkan penggabungan deklarasi, sehingga deklarasi kedua dengan nama yang sama menjadi kesalahan pengidentifikasi duplikat.
  • Mengonversi alias tipe menjadi antarmuka hanya berfungsi untuk bentuk objek. Serikat pekerja, tupel, dan tipe yang dipetakan harus tetap sebagai alias tipe.
  • Pesan kesalahan dan kursor editor mungkin menampilkan jenis yang berbeda, yang dapat mengejutkan rekan satu tim tetapi tidak mengubah perilaku.

Lakukan perubahan dalam satu permintaan tarik terfokus, jalankan kompiler dalam mode ketat dan rangkaian pengujian Anda, dan hindari mencampurkannya dengan pekerjaan fitur sehingga peninjau dapat melihat bahwa tidak ada perubahan lain.

Penutup

Pertanyaan antarmuka vs tipe memiliki jawaban yang tenang: keduanya tumpang tindih untuk objek, masing-masing memiliki beberapa kemampuan unik, dan konsistensi lebih penting daripada pilihan. Gunakan antarmuka untuk bentuk dan tipe untuk hal lainnya, kecuali tim Anda menginginkan sebaliknya. Untuk melihat sendiri perbedaannya, salin contoh di atas ke dalam file dan jalankan tsc --noEmit --strict di dalamnya.

Pertanyaan yang sering diajukan

Apa perbedaan antara antarmuka dan mengetik di TypeScript?

Keduanya dapat mendeskripsikan bentuk objek. Hanya tipe yang dapat memberi nama gabungan, tupel, dan tipe terkomputasi, sementara hanya antarmuka yang mendukung penggabungan deklarasi.

Haruskah saya menggunakan antarmuka atau mengetik untuk alat peraga React?

Keduanya berfungsi dengan baik. Banyak tim menggunakan antarmuka untuk alat peraga, sementara yang lain lebih memilih tipe untuk konsistensi dengan serikat pekerja. Pilih satu dan terapkan di seluruh proyek.

Bisakah suatu tipe memperluas antarmuka?

Ya, dengan menggunakan persimpangan seperti tipe Admin = Pengguna & { izin: string[] }. Antarmuka juga dapat memperluas alias tipe objek.

Apakah antarmuka lebih cepat dari tipe?

Panduan kinerja TypeScript mendukung perluasan antarmuka pada persimpangan besar dalam basis kode besar. Dalam proyek-proyek biasa, perbedaannya tidak akan terlihat.

Apa itu penggabungan deklarasi?

Ini adalah ketika dua antarmuka dengan nama yang sama dalam lingkup yang sama digabungkan menjadi satu. Jenis alias tidak dapat digabungkan, dan nama duplikat menyebabkan kesalahan.

Teruslah belajar

Bekerja dengan Stack Quora

Butuh bantuan dengan pengujian, WordPress atau SEO?

Kami membantu tim mengirimkan perangkat lunak yang lebih baik dan mengembangkan situs mereka. Beritahu kami apa yang sedang Anda kerjakan dan kami akan menyarankan langkah selanjutnya yang jelas.

Teruslah membaca

Panduan lebih lanjut tentang pengujian, AI & pengembangan modern

Menikmati artikel ini? Pilih topik dan langsung masuk ke tutorial terbaru kami.

Kecerdasan buatan

Penjelasan Halusinasi AI: Mengapa Model Bahasa Memperbaiki Masalah dan Cara Menguranginya

Halusinasi AI menjelaskan: apa itu, mengapa model bahasa memproduksinya, tipe umum, cara menguranginya dengan landasan dan petunjuk, dan pemeriksaan…

Baca artikel →
DevOps

Penjelasan Variabel Lingkungan: File .env, Rahasia, dan Konfigurasi Dilakukan dengan Benar

Variabel lingkungan dijelaskan dengan contoh Python yang kami jalankan: membaca dan mengaturnya, mengapa setiap nilai berupa string, file .env, pewa…

Baca artikel →
Pengembangan perangkat lunak

Penjelasan Pembatasan Kecepatan API: Algoritma, Header, dan Penanganan 429 Kesalahan

Pembatasan laju API dijelaskan dengan simulasi yang kami jalankan: keranjang token, jendela tetap, jendela geser, respons 429, header batas laju, pe…

Baca artikel →
Otomatisasi pengujian

Mengejek dengan Python: unittest.mock, patch dan Kesalahan yang Membuat Tes Berbohong

Mengejek dengan Python dengan unittest.mock, menguji: Mock dan return_value, side_effect, menambal di mana nama digunakan, spesifikasi dan autospec,…

Baca artikel →
Pengujian perangkat lunak

Penjelasan Cakupan Kode: Cakupan Jalur vs Cabang dan Apa Arti 100% Sebenarnya

Cakupan kode dijelaskan dengan coverage.py yang sebenarnya dijalankan: cakupan garis, cabang dan kondisi, membaca laporan, mengapa cakupan 100% masi…

Baca artikel →
Basis data & SQL

DELETE vs TRUNCATE vs DROP dalam SQL: Perbedaan, Rollback dan Kapan Menggunakan Masing-Masing

DELETE vs TRUNCATE vs DROP dijelaskan dengan SQL yang diuji: apa yang dihapus, rollback, pemicu, reset identitas, kecepatan, dan perbedaan PostgreSQ…

Baca artikel →
Basis data & SQL

Penjelasan Tampilan SQL: Membuat, Menggunakan, dan Menghindari Kesalahan, Dengan Contoh

Tampilan SQL dijelaskan dengan kueri yang kami jalankan: membuat tampilan, hasil langsung, menyembunyikan kolom, kinerja, tampilan yang dapat diperb…

Baca artikel →
Pengembangan perangkat lunak

Antarmuka TypeScript vs Tipe: Perbedaan Nyata, Diuji Dengan Kompiler

Antarmuka TypeScript vs tipe, diperiksa dengan kompiler sebenarnya: apa yang bisa dilakukan keduanya, apa yang hanya bisa dilakukan satu orang, peng…

Baca artikel →
Pengembangan perangkat lunak

Penjelasan Python *args dan **kwargs: Fungsi Fleksibel Dengan Contoh Jelas

Python *args dan **kwargs dijelaskan dengan kode yang kami jalankan: pengepakan dan pembongkaran, urutan parameter, argumen hanya kata kunci dan pos…

Baca artikel →
Pengembangan perangkat lunak

Fungsi Python Lambda: Sintaks, Kegunaan Sebenarnya, dan Kapan Tidak Digunakan

Fungsi python lambda dijelaskan dengan kode yang kami jalankan: sintaksis, pengurutan dengan kunci, peta dan filter, penutupan, jebakan pengikatan a…

Baca artikel →
Kecerdasan buatan

Apa Itu Agen AI? Cara Kerjanya, Dengan Agent Loop Sederhana yang Dapat Anda Jalankan

Apa itu agen AI? Panduan sederhana tentang loop agen, alat, memori, dan pagar pembatas, dengan loop Python kecil yang kami jalankan, risiko nyata da…

Baca artikel →
DevOps

Pemantauan vs Observabilitas: Perbedaan Nyata, Dengan Log, Metrik, dan Jejak

Penjelasan pemantauan vs observabilitas: kegagalan yang diketahui dan tidak diketahui, log, metrik dan jejak, penelusuran insiden checkout, sinyal e…

Baca artikel →
DevOps

Volume Docker vs Bind Mounts: Pertahankan Data Kontainer dengan Cara yang Benar

Volume Docker vs pengikatan pengikat dijelaskan: mengapa data kontainer menghilang, volume yang diberi nama, pengikatan pengikatan, tmpfs, contoh Tu…

Baca artikel →
Otomatisasi pengujian

TDD vs BDD: Perbedaan Utama, Satu Fitur Dibangun dengan Dua Cara dan Kapan Menggunakan Masing-masing

TDD vs BDD dijelaskan dengan satu fitur diskon yang dibuat dengan dua cara: refactor merah-hijau dengan kode yang kami jalankan, skenario Mengingat-…

Baca artikel →
Pengembangan perangkat lunak

Git merge vs rebase: perbedaan, contoh, dan kapan memakai masing-masing

Git merge vs rebase dijelaskan dengan keluaran log nyata, tabel perbandingan, aturan emas rebase, dan alur kerja tim yang aman.

Baca artikel →
Pengembangan perangkat lunak

List Comprehension Python: Sintaks, Contoh, dan Kapan Harus Dihindari

List comprehension Python dijelaskan: sintaks, filter, if-else, perulangan bersarang, waktu yang diukur, dan kapan perulangan for biasa lebih baik.

Baca artikel →
Basis data & SQL

Penjelasan SQL JOIN dengan Contoh (Inner, Left, Right, Full)

Pahami SQL JOIN langkah demi langkah dengan tabel dan query contoh: INNER, LEFT, RIGHT, FULL, CROSS, dan SELF, plus kesalahan umum dan tips performa.

Baca artikel →