Ders 08 / 23
Tip Takma Adları
type bildiriminin arayüzden farkları: her tipi adlandırabilme, bildirim birleştirmenin bulunmaması, döngüsel başvuru kuralları, takma adla sınıf sözleşmesi ve seçim ölçütü.
İçindekiler
Aynı ölçüm modeli önceki konuda type ile, bu konunun ilk dersinde interface ile
yazıldı. İki bildirim biçimi çoğu durumda birbirinin yerine geçer; eşdeğer değildirler.
Tip takma adı (type alias), var olan bir tipe ad veren bildirimdir. Yeni bir tip
yaratmaz — type Kimlik = string bildiriminden sonra Kimlik ile string aynı tiptir ve
birbirinin yerine kullanılabilir. Arayüz ise adlandırılmış bir nesne tipi tanımlar.
Bu ders, farkın nerede ortaya çıktığını ve hangisinin ne zaman seçileceğini kurar.
Her Tipi Adlandırabilme
Takma ad, herhangi bir tipe ad verebilir. Arayüz yalnızca nesne ve çağrılabilir yapıları tanımlayabilir:
type Birim = "C" | "Pa" | "%"; type Kimlik = string; type Aralik = [alt: number, ust: number]; type Donusturucu = (deger: number) => number; const birim: Birim = "C"; const aralik: Aralik = [-40, 85]; const kelvine: Donusturucu = (d) => d + 273.15; console.log(birim, aralik, kelvine(21.4));
Çıktı:
C [ -40, 85 ] 294.54999999999995
Dördünün hiçbiri arayüzle yazılamaz. Birleşim, ilkel tip ve demet nesne tipi değildir; fonksiyon tipi arayüzle yazılabilir ama çok daha uzun bir yazım gerektirir. Sonraki konudaki eşlenmiş, koşullu ve şablon dizgi tipleri de yalnızca takma adla adlandırılabilir.
Çıktının son değerine dikkat: 21.4 + 273.15 işlemi 294.55 değil
294.54999999999995 verir. Tip sistemi number tipini doğru saymıştır; kayan noktalı
gösterimin kesinlik sınırı ise onun alanı değildir. Bu, ilk derste sayılan
“kanıtlanmayanlar” listesinin somut bir örneğidir.
Bildirim Birleştirme Yok
Arayüzler aynı adla yeniden bildirilip birleştirilebiliyordu. Takma adlarda bu yoktur:
type Olcum = { kimlik: string }; type Olcum = { deger: number };
h2.ts(1,6): error TS2300: Duplicate identifier 'Olcum'. h2.ts(2,6): error TS2300: Duplicate identifier 'Olcum'.
Tanı iki kez gelir, çünkü her iki bildirim de çakışmanın tarafıdır.
Bu, takma adın sınırı değil güvencesidir: bir takma adın tanımı, yazıldığı yerde tamdır. Başka bir dosyanın o tipe alan eklemesi olanaksızdır. Kendi kod tabanının veri modellerinde bu öngörülebilirlik genellikle istenir.
Karşı yönde, bir arayüz genişletme yoluyla takma addan türetilebilir:
type SayisalOlcum = { kimlik: string; deger: number }; interface ZamanliOlcum extends SayisalOlcum { zaman: number; } const k: ZamanliOlcum = { kimlik: "s-01", deger: 21.4, zaman: 1 }; console.log(k);
Bu dosya hatasız derlenir. Ancak takma ad bir nesne tipi değilse genişletme başarısız olur:
type SayisalOlcum = { kimlik: string; deger: number }; type MetinselOlcum = { kimlik: string; metin: string }; type Kayit = SayisalOlcum | MetinselOlcum; interface Genisletme extends Kayit { zaman: number; }
h7.ts(5,30): error TS2312: An interface can only extend an object type or intersection of object types with statically known members.
Bir birleşimi genişletmenin anlamı yoktur: Genisletme tipinin hangi üyeyi devralacağı
belirsizdir. Aynı işlemi kesişimle yazmak ise geçerlidir —
type Genisletme = Kayit & { zaman: number } bildirimi, her iki üyeye zaman alanı ekleyen
bir birleşim üretir.
Döngüsel Başvuru
Ölçüm kayıtları iç içe geçen bir yapıya dönüştüğünde, tip kendisine başvurmak zorunda kalır. Nesne alanı içindeki başvuru geçerlidir:
type OlcumDugumu = { kimlik: string; deger: number; altKayitlar: OlcumDugumu[]; }; const kok: OlcumDugumu = { kimlik: "kazan-2", deger: 21.4, altKayitlar: [{ kimlik: "s-01", deger: 21.4, altKayitlar: [] }], }; function toplamDugum(dugum: OlcumDugumu): number { return 1 + dugum.altKayitlar.reduce((t, a) => t + toplamDugum(a), 0); } console.log(toplamDugum(kok));
Dosya hatasız derlenir, çıktısı 2dir.
Buna karşılık doğrudan döngüsel bir başvuru reddedilir:
type Zincir = Zincir | null; declare const z: Zincir; console.log(z);
h3.ts(1,6): error TS2456: Type alias 'Zincir' circularly references itself.
Ayrım şudur: OlcumDugumu başvurusu bir nesne alanının içindedir ve derleyici o alanın
tipini yalnızca gerektiğinde çözer. Zincir bildirimi ise kendi tanımını çözmek için yine
kendini gerektirir; sonlanmayan bir açılımdır. Özyinelemeli tip tanımlarının kuralları
İleri Tipler konusunda ayrıntılı ele alınacaktır.
Takma Adla Sınıf Sözleşmesi
Bir sınıfın karşılayacağı sözleşme takma adla da yazılabilir. Takma ad bir nesne tipini
adlandırdığı sürece implements bildirimi arayüzdekiyle aynı biçimde çalışır:
type Olcum = { kimlik: string; deger: number }; class DosyaKaydi implements Olcum { constructor( readonly kimlik: string, readonly deger: number, ) {} } const kayit: Olcum = new DosyaKaydi("s-01", 21.4); console.log(kayit.kimlik, kayit.deger);
Çıktı s-01 21.4tür.
Sınır, genişletmedeki sınırla aynıdır: takma ad bir birleşimi adlandırıyorsa gerçekleştirilemez.
type SayisalOlcum = { kimlik: string; deger: number }; type MetinselOlcum = { kimlik: string; metin: string }; type Kayit = SayisalOlcum | MetinselOlcum; class DosyaKaydi implements Kayit { constructor(readonly kimlik: string) {} }
u2.ts(5,29): error TS2422: A class can only implement an object type or intersection of object types with statically known members.
Gerekçe de aynıdır: sınıfın hangi üyeyi karşılayacağı belirsizdir. Bir sınıfın “ya şu ya bu biçimde” olması, tek bir bildirimle ifade edilemez. Böyle bir modelde sözleşme, birleşimin her üyesi için ayrı sınıflarla karşılanır ve birleşim yalnızca değer düzeyinde kullanılır.
Seçim Ölçütü
İki bildirim biçimi arasındaki farklar bir tabloda toplanabilir:
| Ölçüt | interface |
type |
|---|---|---|
| Nesne tipi tanımlar | Evet | Evet |
| Birleşim, demet, ilkel adlandırır | Hayır | Evet |
| Aynı adla yeniden bildirim | Birleşir | TS2300 |
| Genişletme | extends (bildirimde sınanır) |
& (sessizce indirgenir) |
| Sınıfla gerçekleştirme | implements |
implements (nesne tipiyse) |
| Eşlenmiş, koşullu tip | Hayır | Evet |
Tablodan uygulanabilir bir ölçüt çıkar:
Nesne biçimindeki sözleşmeler için arayüz. Bir veri kaydının alanları, bir servisin sunduğu yöntemler, bir sınıfın karşılayacağı sözleşme. Genişletme sınandığı için hatalar bildirim anında yakalanır; tanı iletileri ad taşır.
Diğer her şey için takma ad. Birleşimler, ayırt edici birleşimler, demetler, fonksiyon tipleri, tip düzeyinde hesaplanan tipler. Bu tiplerin arayüz karşılığı ya yoktur ya zorlamadır.
Bu kursta ölçüm kaydının kendisi arayüzle, durumları ve türetilmiş tipleri takma adla yazılacaktır:
interface Olcum { readonly kimlik: string; sensor: string; deger: number; birim: "C" | "Pa" | "%"; zaman: number; } type OlcumDurumu = | { durum: "gecerli"; olcum: Olcum } | { durum: "hatali"; kimlik: string; kod: string }; function ozet(kayit: OlcumDurumu): string { return kayit.durum === "gecerli" ? `${kayit.olcum.kimlik}=${kayit.olcum.deger}${kayit.olcum.birim}` : `${kayit.kimlik}: ${kayit.kod}`; } console.log( ozet({ durum: "gecerli", olcum: { kimlik: "s-01", sensor: "sicaklik", deger: 21.4, birim: "C", zaman: 1706000000000, }, }), ); console.log(ozet({ durum: "hatali", kimlik: "s-02", kod: "E17" }));
Çıktı:
s-01=21.4C s-02: E17
İki bildirim biçiminin iş bölümü burada görülür: Olcum bir kaydın biçimidir ve
büyüyebilir; OlcumDurumu ise kapalı bir seçenek kümesidir ve büyümesi kasıtlı bir karar
olmalıdır.
Özet
- Tip takma adı var olan bir tipe ad verir; birleşim, demet, ilkel ve fonksiyon tipleri dahil her tipi adlandırabilir.
- Arayüzler aynı adla yeniden bildirilip birleşir; takma adın ikinci bildirimi
TS2300tanısı verir ve bu, tanımın tek yerde tam olmasını güvenceye alır. - Bir arayüz nesne tipindeki takma adı genişletebilir; birleşim tipini genişletemez.
- Nesne alanı içindeki döngüsel başvuru geçerlidir; doğrudan döngüsel takma ad
TS2456tanısı verir. - Nesne tipini adlandıran bir takma ad
implementsile gerçekleştirilebilir; birleşimi adlandıran takma adTS2422tanısı verir. - Ölçüt: nesne biçimindeki sözleşmeler arayüzle, birleşimler ve tip düzeyinde hesaplanan tipler takma adla yazılır.
Sonraki Adım
Buraya kadarki sözleşmeler yalnızca veriyi ve işlem imzalarını tanımladı; gerçekleştirim her seferinde ayrı bir fonksiyondan geldi. Sınıflar bu ikisini bir arada tutar ve TypeScript, sınıflara görünürlük denetimi ekler. Sonraki ders erişim belirteçlerini, soyut sınıfları ve bunların derlenmiş çıktıda ne bıraktığını ele alacak.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.