Rumah > hujung hadapan web > tutorial css > Demystifying Typescript Discriminated Union

Demystifying Typescript Discriminated Union

Joseph Gordon-Levitt
Lepaskan: 2025-03-14 10:57:09
asal
960 orang telah melayarinya

Demystifying Typescript Discriminated Union

TypeScript adalah alat yang berkuasa untuk membina aplikasi JavaScript berskala dan hampir menjadi standard untuk projek Web JavaScript yang besar. Walau bagaimanapun, untuk pemula, TypeScript juga mempunyai beberapa perkara yang rumit, salah satunya adalah membezakan antara jenis kesatuan.

Pertimbangkan kod berikut:

 Kucing antara muka {
  Berat: Nombor;
  Whiskers: Nombor;
}
Antara muka anjing {
  Berat: Nombor;
  Mesra: Boolean;
}
Let Animal: Anjing |
Salin selepas log masuk
Salin selepas log masuk

Ramai pemaju akan terkejut mendapati bahawa apabila mengakses animal , hanya atribut weight yang sah, manakala whiskers dan atribut friendly tidak sah. Artikel ini akan menjelaskan sebab -sebabnya.

Sebelum kita menyelam ke dalamnya, mari kita mengkaji semula jenis struktur dan nominal dengan cepat, yang akan membantu memahami perbezaan TypeScript antara jenis kesatuan.

Jenis struktur

Cara terbaik untuk memahami jenis struktur adalah membandingkannya dengan jenis nominal. Kebanyakan bahasa yang ditaip yang mungkin anda gunakan adalah ditaip secara nominal. Sebagai contoh, kod C# (Java atau C serupa):

 kelas foo {
  public int x;
}
kelas blah {
  public int x;
}
Salin selepas log masuk

Walaupun Foo dan Blah mempunyai struktur yang sama, mereka tidak dapat memberikan nilai antara satu sama lain. Kod berikut:

 Blah b = baru foo ();
Salin selepas log masuk

Kesalahan berikut akan dihasilkan:

<code>无法隐式转换类型“Foo”为“Blah”</code>
Salin selepas log masuk

Struktur kelas ini tidak penting. Pembolehubah jenis Foo hanya boleh diberikan kepada contoh kelas Foo (atau subkelasnya).

Typescript, sebaliknya, mengamalkan jenis struktur. TypeScript menganggap mereka serasi jika kedua -dua jenis mempunyai struktur yang sama.

Oleh itu, kod berikut berfungsi dengan baik:

 kelas foo {
  x: nombor = 0;
}
kelas blah {
  x: nombor = 0;
}
Let f: foo = new blah ();
Let B: blah = baru foo ();
Salin selepas log masuk

Koleksi jenis sebagai nilai yang sepadan

Mari kita jelaskan ini lebih lanjut. Memandangkan kod berikut:

 kelas foo {
  x: nombor = 0;
}

Biarkan f: foo;
Salin selepas log masuk

f ialah pembolehubah yang boleh memegang sebarang objek yang sama dengan struktur kelas Foo , dalam kes ini, yang bermaksud x harta yang mewakili nombor. Ini bermakna walaupun objek JavaScript biasa boleh diterima.

 Biarkan f: foo;
f = {
  x: 0
};
Salin selepas log masuk

Jenis Kesatuan

Mari kembali ke kod pada permulaan artikel ini:

 Kucing antara muka {
  Berat: Nombor;
  Whiskers: Nombor;
}
Antara muka anjing {
  Berat: Nombor;
  Mesra: Boolean;
}
Salin selepas log masuk

Kami tahu:

 biarkan haiwan: anjing;
Salin selepas log masuk

Buat animal apa -apa objek dengan struktur yang sama seperti antara muka Dog . Jadi apa maksud kod berikut?

 Let Animal: Anjing |
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Ini mentakrifkan jenis animal sebagai objek yang sepadan dengan antara muka Dog , atau mana -mana objek yang sepadan dengan antara muka Cat .

Jadi mengapa animal sekarang hanya membenarkan kita mengakses atribut weight ? Ringkasnya, ia adalah kerana TypeScript tidak tahu jenisnya. TypeScript tahu animal mestilah Dog atau Cat , tetapi mungkin sama ada. Jika kita dibenarkan mengakses harta friendly , tetapi dalam contoh animal sebenarnya Cat dan bukan Dog , ia boleh mengakibatkan ralat runtime. Begitu juga dengan atribut whiskers .

Jenis Kesatuan adalah kesatuan nilai yang sah, bukan kesatuan atribut. Pemaju sering menulis kod seperti ini:

 Let Animal: Anjing |
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Dan mengharapkan animal mempunyai kesatuan Dog dan sifat Cat . Tetapi ini adalah satu lagi kesilapan. Ini menentukan animal mempunyai nilai yang sepadan dengan sendi Dog yang sah dan nilai Cat yang sah. Tetapi TypeScript hanya membolehkan anda mengakses sifat yang diketahui ada. Pada masa ini, ini bermakna semua jenis sifat dalam Kesatuan.

Jenis penyempitan

Sekarang, kita ada:

 Let Animal: Anjing |
Salin selepas log masuk
Salin selepas log masuk
Salin selepas log masuk

Apabila animal adalah Dog , bagaimanakah kita memperlakukannya dengan betul sebagai Dog dan sifat akses pada antara muka Dog , dan juga mengendalikannya ketika Cat ? Pada masa ini, kita boleh menggunakan pengendali in . Ini adalah pengendali JavaScript lama yang anda tidak dapat melihat dengan kerap, yang membolehkan kami menguji sama ada sesuatu harta dalam objek. Contohnya:

 biarkan o = {a: 12};

"A" dalam O;
"X" dalam O;
Salin selepas log masuk

Ternyata bahawa TypeScript sangat terintegrasi dengan pengendali in . Mari lihat cara menggunakan:

 Let Animal: Dog |

jika ("mesra" dalam haiwan) {
  console.log (haiwan.friendly);
} else {
  Console.log (Animal.Whiskers);
}
Salin selepas log masuk

Kod ini tidak akan menghasilkan kesilapan. Di dalam blok if , TypeScript tahu bahawa terdapat harta friendly , jadi menukarkan animal kepada Dog . Di dalam blok else , TypeScript juga merawat animal sebagai Cat . Anda juga boleh melihat ini dalam editor kod dengan melayang tetikus anda ke atas objek animal di blok ini.

Jenis kesatuan yang membezakan

Anda mungkin mengharapkan catatan blog berakhir di sini, tetapi malangnya, menyempitkan jenis kesatuan sangat terhad dengan memeriksa jika sifat itu wujud. Ia berfungsi dengan baik untuk jenis Dog dan Cat mudah kita, tetapi apabila kita mempunyai lebih banyak jenis dan lebih banyak pertindihan antara jenis ini, perkara -perkara dengan mudah dapat menjadi lebih kompleks dan rapuh.

Di sinilah membezakan jenis kesatuan yang berguna. Kami akan menyimpan segala -galanya dari sebelumnya, hanya menambah harta kepada setiap jenis, yang satu -satunya tujuannya adalah untuk membezakan (atau "membezakan") jenis ini:

 Kucing antara muka {
  Berat: Nombor;
  Whiskers: Nombor;
  Animal_type: "kucing";
}
Antara muka anjing {
  Berat: Nombor;
  Mesra: Boolean;
  Animal_type: "anjing";
}
Salin selepas log masuk

Perhatikan atribut ANIMAL_TYPE pada kedua -dua jenis. Jangan salahkan untuk rentetan dengan dua nilai yang berbeza; ANIMAL_TYPE: "CAT";

Sekarang pemeriksaan kami menjadi lebih dipercayai:

 Let Animal: Dog |

jika (haiwan.animal_type === "anjing") {
  console.log (haiwan.friendly);
} else {
  Console.log (Animal.Whiskers);
}
Salin selepas log masuk

Pemeriksaan ini akan menjadi kebocoran dengan mengandaikan bahawa setiap jenis yang mengambil bahagian dalam kesatuan mempunyai nilai yang berbeza dari atribut ANIMAL_TYPE .

Satu -satunya kelemahan adalah bahawa anda kini perlu berurusan dengan harta baru. Setiap kali contoh Dog atau Cat dicipta, anda mesti memberikan nilai yang unik untuk ANIMAL_TYPE . Tetapi jangan bimbang tentang melupakan, kerana TypeScript akan mengingatkan anda. ?

Bacaan lanjut

Jika anda ingin mengetahui lebih lanjut, saya cadangkan membaca dokumentasi TypeScript mengenai jenis penyempitan. Ini akan memberi kita pandangan yang lebih mendalam mengenai apa yang kita sedang berbincang di sini. Terdapat seksyen mengenai penegasan jenis dalam pautan ini. Ini membolehkan anda menentukan pemeriksaan tersuai anda sendiri untuk menyempitkan jenis tanpa menggunakan diskriminator jenis atau bergantung pada kata kunci in .

kesimpulannya

Pada permulaan artikel ini, saya berkata, dalam contoh berikut, mengapa weight adalah satu -satunya harta yang boleh diakses:

 Kucing antara muka {
  Berat: Nombor;
  Whiskers: Nombor;
}
Antara muka anjing {
  Berat: Nombor;
  Mesra: Boolean;
}
Let Animal: Anjing |
Salin selepas log masuk
Salin selepas log masuk

Apa yang kita pelajari ialah TypeScript hanya tahu animal boleh menjadi Dog atau Cat , tetapi tidak kedua -duanya. Oleh itu, kita hanya boleh mendapatkan weight , yang merupakan satu -satunya harta awam di antara keduanya.

Konsep jenis kesatuan yang membezakan adalah cara TypeScript membezakan objek ini, dan pendekatan ini sangat berskala, walaupun untuk koleksi objek yang lebih besar. Oleh itu, kita perlu membuat harta ANIMAL_TYPE baru pada kedua -dua jenis yang memegang satu nilai literal yang boleh kita gunakan untuk memeriksa. Sudah tentu, ini adalah satu lagi perkara yang perlu dijejaki, tetapi ia juga menghasilkan hasil yang lebih dipercayai - yang mana yang kita inginkan dari TypeScript di tempat pertama.

Atas ialah kandungan terperinci Demystifying Typescript Discriminated Union. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan