Ders 06 / 23
Sabit Tipler ve as const
Tek değerli sabit tipler, as const ile genişletmenin durdurulması, sabit bir listeden birleşim tipi türetme ve satisfies işlecinin tip açıklamasından farkı.
İçindekiler
Ayırt edici birleşimin çalışması için alanların sabit tipte olması gerekiyordu. Tip çıkarımı dersi ise ters yönde bir kural koymuştu: nesne alanlarının tipi kendiliğinden genişletilir ve sabit tip kaybolur.
Bu ders bu gerilimi çözer. Önce sabit tiplerin ne olduğu netleştirilir, sonra genişletmeyi
durduran as const yazımı, en sonunda da tipi daraltmadan sınayan satisfies işleci ele
alınır.
Terim uyarısı: burada sabit tip (literal type) ile kastedilen, tek bir değeri içeren bir tiptir. Programlama Temelleri kursundaki sabit (constant) kavramıyla — program boyunca aynı değere bağlı ad — akrabadır ama aynı şey değildir; biri değerin tipiyle, diğeri bağlamanın değişmezliğiyle ilgilidir.
Sabit Tip Nedir
Her değerin, yalnızca kendisini içeren bir tipi vardır. "C" bir dizgi değeridir, "C"
aynı zamanda tek elemanlı bir tiptir. Bu tiplere sabit tip denir ve dizgi, sayı ve
mantıksal değerler için tanımlıdır.
Sabit tipler tek başlarına pek kullanışlı değildir — const x: "C" = "C" bildiriminin
söylediği ek bir şey yoktur. Değerleri, birleşimde ortaya çıkar: "C" | "Pa" | "%" tipi,
üç değerli bir kümedir ve dördüncü bir değeri reddeder.
Genişletme ve as const
Aynı nesne sabitinin iki biçimde bildirilmesi, çıkarılan tipleri karşılaştırmayı sağlar:
export const dogrudan = { kimlik: "s-01", birim: "C", deger: 21.4 }; export const dondurulmus = { kimlik: "s-01", birim: "C", deger: 21.4 } as const; export const birimler = ["C", "Pa", "%"]; export const birimlerSabit = ["C", "Pa", "%"] as const;
Dosya sabit.ts adıyla kaydedilip
tsc --strict --target es2022 --declaration --emitDeclarationOnly sabit.ts komutuyla
derlendiğinde üretilen sabit.d.ts dosyası:
export declare const dogrudan: { kimlik: string; birim: string; deger: number; }; export declare const dondurulmus: { readonly kimlik: "s-01"; readonly birim: "C"; readonly deger: 21.4; }; export declare const birimler: string[]; export declare const birimlerSabit: readonly ["C", "Pa", "%"];
as const yazımı üç şeyi birden yapar:
- Alanların tiplerini genişletmez; her alan kendi sabit tipini korur.
- Tüm alanları salt okunur (readonly) işaretler.
- Dizi sabitini dizi değil demet olarak tipler:
string[]yerinereadonly ["C", "Pa", "%"].
Üçüncü madde önemlidir. birimler dizisinin tipi eleman sayısını unutmuştur;
birimlerSabit demetinin tipi hem sayıyı hem sırayı hem de her konumun değerini bilir.
Salt okunur işaretlemesi de tip düzeyinde bir güvence sağlar:
const birimler = ["C", "Pa", "%"] as const; birimler.push("F");
f2.ts(2,10): error TS2339: Property 'push' does not exist on type 'readonly ["C", "Pa", "%"]'.
as const Çalışma Zamanında Ne Bırakır
Kursun eksenini yeniden sınamak gerekir. Aşağıdaki dosya
tsc --strict --target es2022 ac.ts ile derlendiğinde:
const birimler = ["C", "Pa", "%"] as const; const olcum = { kimlik: "s-01", birim: "C" } as const; console.log(birimler, olcum);
Üretilen JavaScript:
"use strict"; const birimler = ["C", "Pa", "%"]; const olcum = { kimlik: "s-01", birim: "C" }; console.log(birimler, olcum);
node ac.js çıktısı [ 'C', 'Pa', '%' ] { kimlik: 's-01', birim: 'C' } olur.
as const tamamen silinmiştir. Dizi çalışma zamanında sıradan bir dizidir; push
çağrısı JavaScript tarafından kabul edilir. Salt okunurluk, derleyicinin gördüğü kodda
geçerli bir sözdür — çalışma zamanı koruması değil. Gerçek değiştirilemezlik için
Object.freeze gerekir ve o da yüzeyseldir.
Aynı sınır, as const ile işaretlenmiş bir değerin salt okunur olmayan bir tipe
atanmasında da görülür:
type Birim = "C" | "Pa" | "%"; type Olcum = { kimlik: string; deger: number; birim: Birim }; const ham = { kimlik: "s-01", deger: 21.4, birim: "C" } as const; const kayit: Olcum = ham; console.log(kayit.birim); kayit.deger = 22.1; ham.deger = 22.1;
f6.ts(9,5): error TS2540: Cannot assign to 'deger' because it is a read-only property.
Sekizinci satır hata vermez. kayit bildiriminin tipi Olcumdur ve Olcum salt okunur
değildir; aynı nesneye salt okunur olmayan bir başvuru elde edilmiştir. Salt okunurluk
nesnenin değil, başvurunun özelliğidir.
Beşinci satırın kabul edilmesi ise as const yazımının çözdüğü asıl sorunu gösterir:
as const olmadan birim alanı stringe genişler ve atama reddedilirdi.
Sabit Listeden Tip Türetme
as const ile bildirilmiş bir demetten, elemanlarının birleşimi olan bir tip
türetilebilir:
const birimler = ["C", "Pa", "%"] as const; type Birim = (typeof birimler)[number]; const gecerli: Birim = "Pa"; console.log(gecerli, birimler.length); const gecersiz: Birim = "F";
f1.ts(7,7): error TS2322: Type '"F"' is not assignable to type '"C" | "Pa" | "%"'.
İki adım vardır. typeof birimler yazımı, bir değerin tipini alır — burada
readonly ["C", "Pa", "%"]. Ardından [number] indeksi, demetin sayısal indeksle
erişilebilen tüm elemanlarının tiplerinin birleşimini verir. Tanının "C" | "Pa" | "%"
yazması bu türetmenin sonucudur.
Bu kalıbın değeri, aynı bilginin iki kez yazılmasını önlemesidir. Değerler listesi tek yerde durur; hem çalışma zamanında (döngüyle gezilebilir, doğrulamada kullanılabilir) hem de tip düzeyinde kullanılabilir. Numaralandırmanın verdiği “tüm değerleri sayabilme” yeteneği, çalışma zamanı kodu üretmeden elde edilmiş olur.
satisfies: Sınamak Ama Daraltmamak
Bir nesne sabitine tip yazmak iki şeyi birden yapar: sabiti sınar ve bildirimin tipini o tipe sabitler. İkincisi her zaman istenmez:
type Aralik = { alt: number; ust: number }; const aciklamali: Record<string, Aralik> = { sicaklik: { alt: -40, ust: 85 }, }; const sinanan = { sicaklik: { alt: -40, ust: 85 }, } satisfies Record<string, Aralik>; console.log(aciklamali.nem.ust); console.log(sinanan.nem.ust);
f4.ts(12,21): error TS2339: Property 'nem' does not exist on type '{ sicaklik: { alt: number; ust: number; }; }'.
On birinci satır hata vermez. aciklamali bildiriminin tipi Record<string, Aralik>tir;
bu tip “her dizgi anahtar için bir aralık” der, dolayısıyla nem anahtarı da geçerli
sayılır. Çalışma zamanında böyle bir anahtar yoktur ve program çöker.
satisfies işleci sabitin verilen tipe uyduğunu sınar, ama bildirimin tipini
değiştirmez. sinanan bildiriminin tipi, sabitten çıkarılan dar tiptir; olmayan anahtara
erişim on ikinci satırda yakalanır.
Sınama yönü de çalışır:
type Aralik = { alt: number; ust: number }; const araliklar = { sicaklik: { alt: -40, ust: "85" }, } satisfies Record<string, Aralik>; console.log(araliklar.sicaklik.ust);
f5.ts(4,25): error TS2322: Type 'string' is not assignable to type 'number'.
Üç yazımın karşılaştırması:
| Yazım | Sabiti sınar | Bildirimin tipi |
|---|---|---|
const x: T = {...} |
Evet | T |
const x = {...} as T |
Hayır (zorlar) | T |
const x = {...} satisfies T |
Evet | Sabitten çıkarılan dar tip |
Orta satır ilk derste tanıtılan tip iddiasıdır ve bir borçtur. Alt satır, hem sınamayı hem de çıkarımın verdiği ayrıntıyı korur.
Özet
- Sabit tip, tek bir değeri içeren tiptir; kullanışlılığı birleşim içinde ortaya çıkar ve bağlamanın değişmezliğini anlatan “sabit” kavramından ayrıdır.
as constyazımı genişletmeyi durdurur, alanları salt okunur işaretler ve dizi sabitlerini demet olarak tipler.as constçalışma zamanında tamamen silinir; salt okunurluk nesnenin değil başvurunun özelliğidir ve gerçek değiştirilemezlik sağlamaz.- Sabit bir demetten
(typeof x)[number]yazımıyla elemanlarının birleşimi türetilir; aynı bilgi hem değer hem tip düzeyinde tek yerde tutulur. satisfiesişleci sabiti verilen tipe karşı sınar ancak bildirimin dar tipini korur; tip açıklaması sınar ve genişletir, tip iddiası ise yalnızca zorlar.
Sonraki Adım
Bu konu, tek tek değerlerin tiplerini kurdu. Sırada bu tiplerin adlandırılması ve paylaşılması var: bir modülün dışa açtığı sözleşme nasıl yazılır, aynı sözleşmeyi karşılayan farklı gerçekleştirimler nasıl tanımlanır? Sonraki konu arayüzlerle başlayacak ve ölçüm kaydının modelini yeniden kullanılabilir bir sözleşmeye dönüştürecek.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.