TypeScript Arayüzü ve Tür: Derleyiciyle Test Edilen Gerçek Farklılıklar
Arayüzler ve tür takma adları o kadar örtüşüyor ki seçim çoğu zaman keyfi geliyor. Gerçek derleyici hatalarıyla doğrulanan, her birinin diğerinin yapamadığı şeyleri ve ayrıca ekibinizin izleyebileceği basit bir kuralı burada bulabilirsiniz.
- Düz nesne şekilleri için, bir arayüz ve tür takma ad neredeyse birbirinin yerine kullanılabilir.
- Yalnızca
typebirleşimleri, tuple’ları ve diğer nesne olmayan türleri adlandırabilir. - Yalnızca
interface, iki bildirimin birleştirildiği bildirim birleştirmeyi destekler. - Ortak bir kural: nesne şekilleri için arayüzler,
typediğer her şey için tutarlı bir şekilde uygulanır.
Çok az TypeScript sorusu, TypeScript arayüzü ve tür kadar tartışmaya neden olur. Birçok makale, eski sürümlerde önemli olan ancak artık güncelliğini yitirmiş olan farklılıkları listeler. Bu nedenle iddiaları tekrarlamak yerine onları test ettik.
Her farklılığı deneyen bir dosya yazdık ve bunu TypeScript 5.6.3 ile katı modda kontrol ettik. Aşağıda alıntılanan derleyici hataları bu çalıştırmadan kaynaklanmaktadır. Davranışlar sürümler arasında değişiklik gösterebilir; bu nedenle projenizin kullandığı TypeScript sürümünü kontrol edin. Dilde yeniyseniz, Yeni başlayanlar için TypeScript eğitimimiz ile başlayın.
Kısa cevap
interface bir nesnenin şeklini tanımlar ve genişletilebilir veya yeniden açılabilir. type takma adı, nesneler, birleşimler, tanımlama grupları ve işlev türleri dahil olmak üzere herhangi bir türe bir ad verir. Her ikisinin de çalışabildiği yerlerde fark çoğunlukla stildedir.
Nerede aynılar
Bu iki bildirim aynı şekilleri açıklamaktadır:
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, yapısal yazmayı kullanır; bu, adlar yerine şekilleri karşılaştırdığı anlamına gelir. Bu nedenle hiçbir şikayet olmadan bir User bir UserAlias‘e atanabilir. Her ikisi de isteğe bağlı özellikleri, readonly özellikleri, yöntemleri ve dizin imzalarını destekler.
Arayüz ve tip yan yana
| Özellik | arayüz | tip |
|---|---|---|
| Nesne şekilleri | Evet | Evet |
"a" | "b" gibi birlikler |
Hayır | Evet |
| Tuple’lar ve ilkeller | Hayır | Evet |
| Eşlenen ve koşullu türler | Hayır | Evet |
| Beyanname birleştirme | Evet | Hayır, bu bir hata |
| Genişletme | uzanır |
& kavşak |
| Çakışan özellikler | Bildirimde hata | Sessizce never olabilir |
implements ile birlikte kullanılır |
Evet | Evet, eğer bir nesne türü ise |
Yalnızca türün yapabileceği şey
Yararlı türlerin çoğu hiçbir şekilde nesne şekli değildir ve bunları yalnızca tür takma adı adlandırabilir:
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
Birleşim türleri TypeScript’in en değerli özellikleri arasındadır çünkü derleyici liste dışındaki tüm değerleri reddeder:
let s: Status = "paid";
s = "refunded";
// error TS2322: Type '"refunded"' is not assignable to type 'Status'.
Bu, yazım hatalarını ve güncel olmayan değerleri, üretime ulaşmadan önce derleme zamanında yakalar.
Beyanname birleştirme
Aynı adda iki kez bir arayüz bildirirseniz, TypeScript bunları bir arayüzde birleştirir:
interface Settings {
theme: string;
}
interface Settings {
language: string;
}
const settings: Settings = { theme: "dark", language: "en" }; // no error
Aynı şeyi bir tür takma adı ile denediğinizde derleyici reddeder:
type Config = { theme: string };
type Config = { language: string };
// error TS2300: Duplicate identifier 'Config'.
Birleştirme, kitaplıkların türlerini genişletmenize nasıl olanak tanıdığıdır. Örneğin, kitaplığı değiştirmeden genel Window arayüzüne veya bir çerçevenin istek nesnesine özel bir özellik ekleyebilirsiniz. Bu gerçekten faydalı.
İşin diğer tarafı ise birleşmenin tesadüfen gerçekleşebilmesidir. Bir projedeki iki dosya aynı kapsamda aynı ada sahip bir arayüz bildirirse sessizce birleşirler ve bu durum kafa karıştırıcı olabilir. Bir tür takma adı, bu çarpışmayı bir hata haline getirir.
Uzatmalar ve kavşaklar
Her ikisi de mevcut bir türün üzerine inşa etmenize izin verir:
interface Admin extends User {
permissions: string[];
}
type AdminAlias = UserAlias & { permissions: string[] };
Uyumlu özellikler için sonuç aynıdır. Aradaki fark bir çatışmayla ortaya çıkıyor. Bir arayüz bir özelliğin türünü uyumsuz bir şekilde değiştirmeye çalıştığında derleyici bunu hemen bildirir:
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'.
Bir kavşak ilan edildiğinde şikayet etmez. Bunun yerine, çakışan özellik hiçbir değerin sahip olamayacağı bir tür olan never olur. Hata yalnızca daha sonra kullanmaya çalıştığınızda görünür:
type Mixed = { id: number } & { id: string };
const m: Mixed = { id: 1 };
// error TS2322: Type 'number' is not assignable to type 'never'.
Daha sonraki hata, asıl hatadan uzaklaşmaya işaret ettiği için daha kafa karıştırıcıdır. Bu, nesne türlerini oluştururken extends‘i tercih etmenin pratik bir nedenidir.
Sınıflar ve uygulamalar
Bir sınıf, implements kullanarak bir şekli eşleştirme sözü verebilir ve bu, bir arayüz veya nesne türü takma adıyla çalışır:
class Account implements User {
constructor(public id: number, public name: string) {}
}
Bu hatasız derlendi. implements‘in yalnızca sınıfın eşleşip eşleşmediğini kontrol ettiğini unutmayın. Herhangi bir özellik veya kod eklemez. Eşleşecek tek bir şekil olmadığından, bir sınıf bir union tipini uygulayamaz.
Salt okunur ve yardımcı program türleri
Readonly, Partial, Pick ve Omit gibi yardımcı program türleri hem arayüzlerle hem de takma adlarla çalışır. Sonuç olarak, genellikle bir tür takma adıyla adlandırılan yeni bir tür ortaya çıkar:
const r: ReadonlyUser = { id: 3, name: "Dev" };
r.name = "Chitra";
// error TS2540: Cannot assign to 'name' because it is a read-only property.
readonly‘in yalnızca derleme zamanı kontrolü olduğunu unutmayın. Çalışma zamanında nesne sıradan bir JavaScript’tir ve türleri atlayan kodla hala değiştirilebilir.
İpucu: TypeScript, JavaScript’e derlendiğinde türler kaybolur. API yanıtı gibi dışarıdan gelen veriler, yalnızca bir türü olduğu için çalışma zamanında kontrol edilmez. Örneğin bir şema kitaplığıyla doğrulayın. Fetch API eğiticimiz, API yanıtlarının güvenli bir şekilde ele alınmasını kapsar.
Derleyici performansı
TypeScript ekibinin kendi performans kılavuzu, derleyicinin arayüz ilişkilerini daha verimli bir şekilde önbelleğe alabilmesi nedeniyle büyük kesişimler yerine extends kullanan arayüzlerin tercih edilmesini önerir. Küçük ve orta ölçekli projelerde herhangi bir fark görmeniz pek mümkün değildir. Derinlemesine oluşturulmuş türlere sahip çok büyük kod tabanlarında önemli olabilir. Bunu kendimiz ölçmedik.
Hangisini kullanmalısınız?
TypeScript el kitabındaki kılavuza uygun olarak yaygın olarak kullanılan bir kural şudur:
- Nesne şekilleri, özellikle genel API’ler ve sınıfların uyguladığı veya diğerlerinin genişletebileceği her şey için
interfacekullanın. - Birleşimler, tanımlama grupları, işlev türleri ve eşlenen veya hesaplanan türler için
typekullanın.
| Sen tanımlıyorsun | Kullanım |
|---|---|
| Kullanıcı veya Sipariş gibi bir veri modeli | arayüz |
| İzin verilen değerler kümesi | type birlik |
| Sabit uzunlukta bir çift veya üçlü | type demet |
| Geri arama imzası | tip |
| Bir kitaplığın türlerini genişletme | interface, birleştirme yoluyla |
| Mevcut bir türün bir varyasyonu | type bir yardımcı program türüyle |
Bazı takımlar her yerde type‘i kullanır ve bu da işe yarar. En önemli şey tutarlılıktır, bu nedenle bir kural seçin, onu stil kılavuzunuza yazın ve bir linter’in onu uygulamaya koymasına izin verin. TypeScript-eslint’teki ESLint’in consistent-type-definitions kuralı bunu yapabilir.
Yaygın hatalar
- Sonsuz tartışma. Her ikisi de nesneler için uygundur, o yüzden kuralı bir kez belirleyin ve devam edin.
- Yanlışlıkla birleştirme. Aynı kapsamdaki bir arayüz adının yeniden kullanılması, bunları sessizce birleştirir.
- Çakışan kesişimler. Daha sonra kafa karıştırıcı hatalarla
nevertür oluştururlar. - Çalışma sırasında türlere güveniliyor. Bunlar silinir, dolayısıyla harici verileri doğrulayın.
- Hataları susturmak için
anykullanılması. Denetimi kapatır.unknown‘ü tercih edin ve daraltın.
Mevcut bir kod tabanında bunlar arasında geçiş yapma
interface‘i type‘ye veya tam tersine değiştirmek genellikle düz nesne şekilleri için güvenlidir, çünkü TypeScript türleri adlarına göre değil yapılarına göre karşılaştırır. Geçiş yapmadan önce hala birkaç şeyin kontrol edilmesi gerekiyor:
- Bir arabirimin tür takma adına dönüştürülmesi bildirim birleştirmeyi ortadan kaldırır, böylece aynı ada sahip herhangi bir ikinci bildirim yinelenen tanımlayıcı hatasına dönüşür.
- Bir tür takma adının arayüze dönüştürülmesi yalnızca nesne şekilleri için işe yarar. Birleşimler, tanımlama grupları ve eşlenen türler, tür takma adları olarak kalmalıdır.
- Hata mesajları ve editörün gezinmesi, türü farklı şekilde görüntüleyebilir; bu, takım arkadaşlarını şaşırtabilir ancak davranışı değiştirmez.
Değişikliği odaklanmış tek bir çekme isteğinde yapın, derleyiciyi katı modda ve test paketinizde çalıştırın ve bunu özellik çalışmasıyla karıştırmaktan kaçının, böylece gözden geçirenler başka hiçbir şeyin değişmediğini görebilir.
Son sözler
Arayüz ve tür sorusunun sakin bir cevabı var: Nesneler açısından örtüşüyorlar, her birinin birkaç benzersiz yeteneği var ve tutarlılık seçimden daha önemli. Ekibiniz aksini tercih etmedikçe, diğer her şey için şekiller ve türler için arayüzler kullanın. Farkları kendiniz görmek için yukarıdaki örnekleri bir dosyaya kopyalayın ve üzerinde tsc --noEmit --strict komutunu çalıştırın.
Sık sorulan sorular
TypeScript’te arayüz ve tür arasındaki fark nedir?
Her ikisi de nesne şekillerini tanımlayabilir. Yalnızca tür birleşimleri, tanımlama gruplarını ve hesaplanan türleri adlandırabilir, yalnızca arayüz bildirim birleştirmeyi destekler.
React destekleri için arayüz mü yoksa tip mi kullanmalıyım?
Her ikisi de iyi çalışıyor. Birçok ekip destek için arayüzleri kullanırken diğerleri birleşimlerle tutarlılık sağlamak için türü tercih eder. Birini seçin ve proje boyunca uygulayın.
Bir tür bir arayüzü genişletebilir mi?
Evet, Admin = User & { izinler: string[] } gibi bir kesişim kullanarak. Bir arayüz aynı zamanda bir nesne türü takma adını da genişletebilir.
Arayüz yazı tipinden daha mı hızlı?
TypeScript’in performans rehberliği, arayüzün büyük kod tabanlarındaki büyük kesişimlere yayılmasını destekler. Tipik projelerde farkın fark edilmesi pek mümkün değildir.
beyan birleştirme nedir?
Aynı kapsamdaki aynı ada sahip iki arayüzün bir araya getirilmesidir. Tür takma adları birleştirilemez ve yinelenen adlar hataya neden olur.
Öğrenmeye devam et
Test, WordPress veya SEO konusunda yardıma mı ihtiyacınız var?
Ekiplerin daha iyi yazılımlar sunmasına ve sitelerini büyütmesine yardımcı oluyoruz. Bize ne üzerinde çalıştığınızı söyleyin, biz de bir sonraki adım için net bir öneride bulunalım.
Daha fazla kılavuz test, yapay zeka ve modern geliştirme
Bu makaleyi beğendiniz mi? Bir konu seçin ve doğrudan en yeni eğitimlerimize geçin.
Yapay Zeka Halüsinasyonları Açıklandı: Dil Modelleri Neden İşleri Düzeltiyor ve Nasıl Azaltılabilir?
Yapay zeka halüsinasyonları açıkladı: ne olduklarını, dil modellerinin bunları neden ürettiğini, yaygın türlerini, temellendirme ve yönlendirmelerle…
Makaleyi okuyun →DevOpsAçıklanan Ortam Değişkenleri: .env Dosyaları, Sırlar ve Yapılandırma Doğru Yapıldı
Çalıştırdığımız Python örnekleriyle açıklanan ortam değişkenleri: bunları okumak ve ayarlamak, neden her değerin bir dize olduğu, .env dosyaları, sü…
Makaleyi okuyun →Yazılım geliştirmeAPI Hız Sınırlamasının Açıklaması: Algoritmalar, Başlıklar ve 429 Hatalarının Ele Alınması
API hızı sınırlaması, çalıştırdığımız bir simülasyonla açıklanmıştır: belirteç kümesi, sabit pencere, kayan pencere, 429 yanıt, hız sınırı başlıklar…
Makaleyi okuyun →Test otomasyonuPython'da alay etme: Unittest.mock, patch ve Testleri Yalan Yapan Hatalar
Unittest.mock ile Python'da alay etme, test edildi: Sahte ve dönüş_değeri, yan_etki, bir adın kullanıldığı yerde yama uygulama, spesifikasyon ve oto…
Makaleyi okuyun →Yazılım testiKod Kapsamının Açıklaması: Hat ve Şube Kapsamı ve %100'ün Gerçek Anlamı
Kod kapsamı gerçek bir kapsama.py çalışmasıyla açıklanmıştır: hat, şube ve durum kapsamı, bir raporun okunması, %100 kapsamın neden hâlâ hataları ka…
Makaleyi okuyun →Veritabanları ve SQLSQL'de DELETE vs TRUNCATE vs DROP: Farklılıklar, Geri Alma ve Her Biri Ne Zaman Kullanılmalı
DELETE vs TRUNCATE vs DROP test edilmiş SQL ile açıklandı: her birinin neyi kaldırdığı, geri aldığı, tetiklediği, kimlik sıfırlaması, hızı ve Postgr…
Makaleyi okuyun →Veritabanları ve SQLAçıklanan SQL Görünümleri: Örneklerle Tuzakları Oluşturun, Kullanın ve Önleyin
Çalıştırdığımız sorgularla açıklanan SQL görünümleri: görünüm oluşturma, canlı sonuçlar, sütunları gizleme, performans, güncellenebilir ve gerçekleş…
Makaleyi okuyun →Yazılım geliştirmeTypeScript Arayüzü ve Tür: Gerçek Farklılıklar, Derleyiciyle Test Edildi
TypeScript arayüzü ve türü, gerçek derleyiciyle kontrol edildi: her ikisinin de yapabileceği, yalnızca birinin yapabileceği, bildirim birleştirme, g…
Makaleyi okuyun →Yazılım geliştirmePython *args ve **kwargs'ın Açıklaması: Açık Örneklerle Esnek Fonksiyonlar
Python *args ve **kwargs çalıştırdığımız kodla açıklanmıştır: paketleme ve paketten çıkarma, parametre sırası, yalnızca anahtar kelime ve yalnızca k…
Makaleyi okuyun →Yazılım geliştirmePython Lambda İşlevleri: Söz Dizimi, Gerçek Kullanımlar ve Ne Zaman Kullanılmaması Gerektiği
Çalıştırdığımız kodla açıklanan Python lambda işlevleri: sözdizimi, anahtarla sıralama, harita ve filtre, kapatmalar, geç bağlama tuzağı ve normal b…
Makaleyi okuyun →Yapay zekâYapay Zeka Ajanları Nelerdir? Çalıştırabileceğiniz Basit Bir Aracı Döngüsüyle Nasıl Çalışırlar?
Yapay zeka ajanları nedir? Aracı döngüsüne, araçlara, belleğe ve korkuluklara ilişkin basit bir kılavuz, çalıştırdığımız küçük bir Python döngüsü, g…
Makaleyi okuyun →DevOpsİzleme ve Gözlemlenebilirlik: Günlükler, Metrikler ve İzlerle Gerçek Fark
İzleme ve gözlemlenebilirliğin açıklanması: bilinen ve bilinmeyen arızalar, günlükler, ölçümler ve izler, ödeme olayının gözden geçirilmesi, altın s…
Makaleyi okuyun →DevOpsDocker Birimleri ve Bağlama Bağlantıları: Konteyner Verilerini Doğru Şekilde Kalıcılaştırın
Docker birimleri ile bağlama bağlamaları arasındaki karşılaştırma açıklandı: kapsayıcı verilerinin neden kaybolduğu, adlandırılmış birimler, bağlama…
Makaleyi okuyun →Test otomasyonuTDD ve BDD: Temel Farklılıklar, Her İki Şekilde Geliştirilmiş Bir Özellik ve Her Birinin Ne Zaman Kullanılacağı
TDD ve BDD, her iki yönde de oluşturulmuş bir indirim özelliğiyle açıklandı: çalıştırdığımız kodla kırmızı-yeşil-refactor, Verilen-Ne Zaman-O Zaman …
Makaleyi okuyun →Yazılım geliştirmeGit merge vs rebase: farklar, örnekler ve hangisi ne zaman kullanılır
Git merge vs rebase; gerçek log çıktısı, karşılaştırma tablosu, rebase'in altın kuralı ve güvenli bir ekip iş akışıyla anlatılıyor.
Makaleyi okuyun →Yazılım geliştirmePython Liste Üreteci (List Comprehension): Sözdizimi, Örnekler ve Kaçınılacak Durumlar
Python list comprehension anlatımı: sözdizimi, filtreleme, if-else, iç içe döngüler, ölçülmüş süreler ve düz for döngüsünün daha iyi olduğu durumlar.
Makaleyi okuyun →Veritabanları ve SQLSQL JOIN Örneklerle Açıklama (Inner, Left, Right, Full)
SQL JOIN'leri örnek tablolar ve sorgularla adım adım öğrenin: INNER, LEFT, RIGHT, FULL, CROSS ve SELF; yaygın hatalar ve performans ipuçları.
Makaleyi okuyun →