Menu

extends TypeScript: Memperluas Interface atau Type

Kata kunci extends membangun satu tipe dari tipe lain. Pelajari cara meng-extend interface (dari satu atau beberapa interface), memperluas type alias dengan &, menimpa tipe property, mengganti property dengan Omit, dan arti extends di class, generic constraint, dan conditional type.

Halaman ini dilengkapi editor yang bisa dijalankan. Edit, jalankan, dan lihat output-nya seketika.

interface Child extends Parent membuat interface baru dengan setiap member milik Parent ditambah member miliknya sendiri. Nilai bertipe anak bisa dipakai di mana pun induknya diharapkan, karena nilai itu punya semua property induknya.

Kata kunci yang sama muncul di empat tempat di TypeScript, dengan arti yang berkaitan tetapi berbeda:

TempatContohArti
Interfaceinterface Dog extends Animal {}mewarisi member induk
Classclass Dog extends Animal {}mewarisi field dan implementasi method (JavaScript saat runtime)
Parameter generic<T extends Animal>constraint: type argument harus bisa diberikan ke Animal
Conditional typeT extends string ? A : Btes: apakah T bisa diberikan ke string?

Meng-extend Beberapa Interface

Cantumkan beberapa induk setelah extends, dipisahkan dengan koma. Hasilnya punya member dari semua induk itu:

interface Identified {
  id: number;
}

interface Timestamped {
  createdAt: Date;
  updatedAt: Date;
}

interface Post extends Identified, Timestamped {
  title: string;
}

// Post requires id, createdAt, updatedAt and title

Kalau dua induk mendeklarasikan property yang sama dengan tipe yang tidak identik, interface anak menghasilkan error TS2320 (Interface 'Post' cannot simultaneously extend types 'A' and 'B'), kecuali interface anak mendeklarasikan ulang property itu dengan tipe yang bisa diberikan ke keduanya.

Memperluas Type Alias

Type alias type tidak punya klausa extends. Kamu membangun di atasnya dengan intersection, &, yang menggabungkan member dari kedua sisi. Interface juga bisa langsung meng-extend type alias berupa objek, dan type alias bisa meng-intersect interface: keduanya bisa dicampur dengan bebas.

Kedua cara itu berperilaku sama sampai ada property yang bentrok: extends melaporkan property yang bentrok di deklarasinya, sedangkan & diam-diam mengubahnya menjadi never. Perbandingannya ada di halaman interface vs type, dan detail & ada di halaman intersection type.

Menimpa Tipe Property

Interface anak boleh mendeklarasikan ulang property induk, tetapi hanya dengan tipe yang bisa diberikan ke tipe milik induk. Mempersempit string menjadi literal, atau membuang null dari union, diizinkan. Mengubah tipenya menjadi sesuatu yang tidak berhubungan tidak diizinkan:

index.ts(13,11): error TS2430: Interface 'Label' incorrectly extends interface 'Shape'.
  Types of property 'kind' are incompatible.
    Type 'number' is not assignable to type 'string'.

Aturan ini ada supaya Label tetap bisa dipakai di mana pun Shape diharapkan. Kalau kind bisa berupa angka, kode yang ditulis untuk Shape dan memanggil shape.kind.toUpperCase() akan rusak.

Mengganti Property dengan Omit

Kalau kamu benar-benar butuh tipe yang berbeda untuk property warisan, buang dulu property itu dari induknya dengan Omit, lalu deklarasikan yang baru. Kasus yang umum adalah mengonversi data API, di mana id dan tanggal datang sebagai string:

Omit<ApiUser, "id" | "createdAt"> adalah { name: string }, jadi id dan createdAt yang baru tidak bentrok dengan apa pun. Pick, Partial, dan utility type lainnya bisa di-extend dengan cara yang sama.

extends pada Class

class Dog extends Animal adalah pewarisan class JavaScript, dan tidak seperti extends pada interface, ia ada saat runtime: Dog mendapat constructor, field, dan implementasi method milik Animal, dan new Dog(...) instanceof Animal bernilai true. TypeScript menambahkan pemeriksaan tipe di atasnya, seperti kata kunci override:

Sebuah class hanya bisa extends satu class, tetapi bisa implements interface sebanyak apa pun. implements tidak menyalin apa pun: ia hanya memeriksa bahwa class itu mendeklarasikan apa yang diwajibkan interface. super, member protected, dan override dibahas di inheritance.

extends di Generic dan Conditional Type

Di dalam kurung sudut, extends adalah constraint. <T extends { length: number }> menerima type argument apa pun yang punya length berupa angka, dan membuat badan fungsi bisa memakai .length. Di conditional type, T extends U ? X : Y bertanya apakah T bisa diberikan ke U.

Di kedua tempat itu, extends berarti "bisa diberikan ke", hubungan yang sama yang diperiksa oleh bentuk interface. Constraint dibahas secara mendalam di generic constraint, dan tes di level tipe di conditional type.

Pertanyaan yang sering diajukan

Bagaimana cara meng-extend interface di TypeScript?

Tulis interface Child extends Parent { ... }. Interface anak punya setiap property milik induknya ditambah property yang ia deklarasikan sendiri. Untuk meng-extend beberapa interface sekaligus, pisahkan dengan koma: interface C extends A, B { ... }.

Bagaimana cara memperluas type alias di TypeScript?

Type alias tidak bisa memakai extends; gabungkan tipe dengan intersection sebagai gantinya: type Admin = User & { permissions: string[] }. Interface juga bisa langsung meng-extend type alias berupa objek: interface Admin extends User { permissions: string[] }.

Apakah aku bisa menimpa tipe property saat meng-extend interface?

Hanya dengan tipe yang kompatibel dan lebih sempit: kind: "circle" bisa menggantikan kind: string. Tipe yang berbeda, seperti number untuk property string, menghasilkan error TS2430 (Interface 'X' incorrectly extends interface 'Y'). Untuk mengganti property dengan tipe yang tidak berhubungan, buang dulu property itu: interface User extends Omit<ApiUser, "id"> { id: number }.

Apa bedanya extends dan implements?

extends mewarisi: interface mendapat member induknya, dan class mendapat field serta implementasi method dari class induknya. implements hanya memeriksa: class yang mengimplementasikan interface harus mendeklarasikan sendiri setiap member, dan tidak mendapat apa pun dari interface itu.

Apa arti extends di generic seperti <T extends string>?

Itu constraint, bukan pewarisan. T extends string berarti type argument-nya harus bisa diberikan ke string, sehingga di dalam fungsi kamu bisa memakai method string pada T. Di conditional type, T extends U ? X : Y adalah sebuah tes: kalau T bisa diberikan ke U, hasilnya X, selain itu Y.

Ilustrasi bahasa pemrograman di Coddy

Belajar coding dengan Coddy

Mulai