TypeScript: Antarmuka vs Jenis

715

Apa perbedaan antara pernyataan ini (antarmuka vs tipe)?

interface X {
    a: number
    b: string
}

type X = {
    a: number
    b: string
};
wonea
sumber
4
Temukan
Sandeep GB
1
Perbedaan
Michael Freidgeim

Jawaban:

574

Sesuai dengan Spesifikasi Bahasa TypeScript :

Tidak seperti deklarasi antarmuka, yang selalu memperkenalkan jenis objek bernama, deklarasi alias tipe dapat memperkenalkan nama untuk semua jenis jenis, termasuk tipe primitif, gabungan, dan persimpangan.

Spesifikasi selanjutnya menyebutkan:

Jenis antarmuka memiliki banyak kesamaan untuk mengetik alias untuk literal jenis objek, tetapi karena jenis antarmuka menawarkan lebih banyak kemampuan, mereka biasanya lebih suka mengetik alias. Misalnya, tipe antarmuka

interface Point {
    x: number;
    y: number;
}

dapat ditulis sebagai jenis alias

type Point = {
    x: number;
    y: number;
};

Namun, melakukannya berarti kemampuan berikut hilang:

  • Antarmuka dapat diberi nama dalam perluasan atau penerapan klausa, tetapi jenis alias untuk tipe objek literal tidak bisa lagi benar sejak TS 2.7.
  • Antarmuka dapat memiliki beberapa deklarasi digabungkan , tetapi alias tipe untuk tipe objek literal tidak bisa.
Pohon Birch Biner
sumber
109
Apa yang dimaksud dengan "deklarasi beberapa gabungan" dalam perbedaan kedua?
jrahhali
66
@ jrahhali jika Anda mendefinisikan antarmuka dua kali, naskah menggabungkan mereka menjadi satu.
Andrey Fedorov
39
@jrahhali jika Anda mendefinisikan jenis dua kali, naskah memberi Anda kesalahan
Andrey Fedorov
18
@jrahhaliinterface Point { x: number; } interface Point { y: number; }
Nahuel Greco
20
Saya percaya poin pertama extends or implementstidak lagi menjadi masalah. Jenis dapat diperpanjang dan diimplementasikan oleh a class. Berikut ini contoh typescriptlang.org/play/…
dark_ruby
777

Pembaruan 2019


Jawaban saat ini dan dokumentasi resmi sudah usang. Dan bagi mereka yang baru mengenal TypeScript, terminologi yang digunakan tidak jelas tanpa contoh. Di bawah ini adalah daftar perbedaan terbaru.

1. Objek / Fungsi

Keduanya dapat digunakan untuk menggambarkan bentuk objek atau fungsi tanda tangan. Tetapi sintaksnya berbeda.

Antarmuka

interface Point {
  x: number;
  y: number;
}

interface SetPoint {
  (x: number, y: number): void;
}

Ketik alias

type Point = {
  x: number;
  y: number;
};

type SetPoint = (x: number, y: number) => void;

2. Jenis Lainnya

Tidak seperti antarmuka, jenis alias juga dapat digunakan untuk jenis lain seperti primitif, serikat pekerja, dan tupel.

// primitive
type Name = string;

// object
type PartialPointX = { x: number; };
type PartialPointY = { y: number; };

// union
type PartialPoint = PartialPointX | PartialPointY;

// tuple
type Data = [number, string];

3. Perpanjang

Keduanya dapat diperpanjang, tetapi sekali lagi, sintaksnya berbeda. Selain itu, perhatikan bahwa antarmuka dan jenis alias tidak saling eksklusif. Antarmuka dapat memperluas alias tipe, dan sebaliknya.

Antarmuka memperluas antarmuka

interface PartialPointX { x: number; }
interface Point extends PartialPointX { y: number; }

Jenis alias meluas alias jenis

type PartialPointX = { x: number; };
type Point = PartialPointX & { y: number; };

Antarmuka memperluas alias tipe

type PartialPointX = { x: number; };
interface Point extends PartialPointX { y: number; }

Ketik alias memperluas antarmuka

interface PartialPointX { x: number; }
type Point = PartialPointX & { y: number; };

4. Implikasinya

Kelas dapat mengimplementasikan antarmuka atau ketik alias, keduanya dengan cara yang persis sama. Namun perlu dicatat bahwa kelas dan antarmuka dianggap cetak biru statis. Oleh karena itu, mereka tidak dapat mengimplementasikan / memperluas jenis alias yang menamai jenis serikat.

interface Point {
  x: number;
  y: number;
}

class SomePoint implements Point {
  x = 1;
  y = 2;
}

type Point2 = {
  x: number;
  y: number;
};

class SomePoint2 implements Point2 {
  x = 1;
  y = 2;
}

type PartialPoint = { x: number; } | { y: number; };

// FIXME: can not implement a union type
class SomePartialPoint implements PartialPoint {
  x = 1;
  y = 2;
}

5. Penggabungan deklarasi

Tidak seperti jenis alias, antarmuka dapat didefinisikan beberapa kali, dan akan diperlakukan sebagai antarmuka tunggal (dengan anggota semua deklarasi digabungkan).

// These two declarations become:
// interface Point { x: number; y: number; }
interface Point { x: number; }
interface Point { y: number; }

const point: Point = { x: 1, y: 2 };
Jabacchetta
sumber
9
Jika dokumentasi resmi sudah usang, di mana informasi yang Anda berikan dapat dikonfirmasi?
iX3
60
Berdasarkan posting ini, tampaknya satu - satunya alasan untuk memilih antarmuka daripada jenis alias adalah jika Anda ingin menggunakan fitur penggabungan deklarasi (poin 5). Di luar itu, mereka sama (dan saya berpendapat bahwa tipe alias menawarkan sintaksis yang lebih ringkas).
Maxedison
17
Saya selalu menggunakan antarmuka untuk tipe objek literal, jika tidak menggunakan tipe lebih masuk akal, juga saya pikir penggabungan deklarasi tidak boleh digunakan dalam cara apa pun, sebenarnya saya tidak akan pernah berharap bahwa antarmuka sedang dinyatakan dalam file lain dari proyek dengan beberapa sifat ekstra, pengecekan tipe dibuat awalnya untuk membuat hidup Anda lebih mudah untuk tidak membuatnya lebih sulit dengan antarmuka seperti ninja ini: D
Ahmed Kamal
8
Jadi pada dasarnya, itu adalah pilihan "hampir pribadi" untuk apa yang benar-benar kita rasa nyaman digunakan? Terlepas dari satu alasan, Anda bisa menggunakan typeatau interface? Saya masih bingung kapan harus menggunakan yang satu atau yang lain.
Joseph Briggs
7
Bisakah seseorang tolong berikan motivasi mengapa Anda ingin penggabungan antarmuka? Itu sepertinya berpotensi membingungkan bagi saya. Mengapa Anda ingin menyebarkan definisi antarmuka Anda di berbagai blok?
Vanquish46
95

Pada TypeScript 3.2 (Nov 2018), berikut ini benar:

masukkan deskripsi gambar di sini

Karol Majewski
sumber
9
Bisakah Anda memberikan informasi lebih lanjut tentang bagaimana tabel / gambar yang Anda berikan dihasilkan? mis. kode sumber atau tautan ke dokumentasi
iX3
23
ya, saya maksud sumber konten, bukan presentasinya.
iX3
3
Saya tidak percaya sebuah kelas dapat memperluas jenis atau antarmuka, dan saya tidak bisa melihat mengapa Anda ingin ??
Dan King
7
Hindari memposting gambar teks, sebaliknya sertakan teks yang sebenarnya langsung ke posting Anda. Gambar teks tidak mudah diurai atau dicari, dan tidak dapat diakses oleh pengguna yang memiliki gangguan penglihatan.
Andrew Marshall
2
Tabel ini tidak memiliki sumber untuk mendukung kontennya dan saya tidak akan bergantung padanya. Sebagai contoh, Anda dapat mendefinisikan tipe rekursif menggunakan typedengan batasan tertentu (dan pada TypeScript 3.7 batasan ini juga hilang). Antarmuka dapat memperluas tipe. Kelas dapat mengimplementasikan tipe. Selain itu, menyajikan data sebagai tangkapan layar dari tabel membuatnya benar-benar tidak dapat diakses oleh orang-orang dengan gangguan penglihatan.
Michał Miszczyszyn
5

Contoh dengan Jenis:

// buat struktur pohon untuk objek. Anda tidak dapat melakukan hal yang sama dengan antarmuka karena kurangnya persimpangan (&)

type Tree<T> = T & { parent: Tree<T> };

// ketik untuk membatasi variabel untuk menetapkan hanya beberapa nilai. Antarmuka tidak memiliki penyatuan (|)

type Choise = "A" | "B" | "C";

// terima kasih pada tipe, Anda dapat mendeklarasikan tipe NonNullable berkat mekanisme kondisional.

type NonNullable<T> = T extends null | undefined ? never : T;

Contoh dengan Antarmuka:

// Anda dapat menggunakan antarmuka untuk OOP dan menggunakan 'implement' untuk mendefinisikan objek / kerangka kelas

interface IUser {
    user: string;
    password: string;
    login: (user: string, password: string) => boolean;
}

class User implements IUser {
    user = "user1"
    password = "password1"

    login(user: string, password: string) {
        return (user == user && password == password)
    }
}

// Anda dapat memperluas antarmuka dengan antarmuka lain

    interface IMyObject {
        label: string,
    }

    interface IMyObjectWithSize extends IMyObject{
        size?: number
    }
Przemek Struciński
sumber
-2

dokumentasi telah dijelaskan

  • Satu perbedaan adalah antarmuka membuat nama baru yang digunakan di mana-mana. Ketik alias tidak membuat nama baru - misalnya, pesan kesalahan tidak akan menggunakan nama alias. Dalam versi lama dari TypeScript, ketik alias tidak dapat diperpanjang atau diimplementasikan dari (atau mereka tidak dapat memperpanjang / mengimplementasikan jenis lain). Pada versi 2.7, alias alias dapat diperluas dengan membuat tipe persimpangan baru
  • Di sisi lain, jika Anda tidak bisa mengekspresikan bentuk dengan antarmuka dan Anda perlu menggunakan jenis gabungan atau tuple, ketik alias biasanya merupakan cara yang harus dilakukan.

Antarmuka vs. Alias ​​Jenis

Liu Lei
sumber