Ders 20 / 23
Bildirim Dosyaları
Tip tanımlarının gerçekleştirimden ayrı taşınması; kaynaktan bildirim üretme, ortam modülü bildirimleri, genel kapsam bildirimi ve dış tiplerin birleştirmeyle genişletilmesi.
İçindekiler
Önceki ders, projenin kendi dosyalarını denetlemeyi sağladı. Dışarıdan gelen kod — tip bilgisi taşımayan bir kütüphane, çalışma zamanının sağladığı genel nesneler — henüz kapsam dışında.
Bildirim dosyası (declaration file), yalnızca tip bilgisi taşıyan ve hiçbir kod
üretmeyen dosyadır. Uzantısı .d.tstir. İki yönde kullanılır: kendi kodunuzun tiplerini
dışa vermek ve dışarıdaki kodun tiplerini içeri almak.
Kaynaktan Bildirim Üretme
Bir kitaplık paketi, gerçekleştirimini JavaScript olarak yayımlar. TypeScript kullanan tüketicilerin tip bilgisine erişebilmesi için bildirim dosyalarının da yayımlanması gerekir. Derleyici bunları kaynaktan üretir:
{ "compilerOptions": { "target": "es2022", "module": "nodenext", "moduleResolution": "nodenext", "strict": true, "declaration": true, "rootDir": "src", "outDir": "dist" }, "include": ["src"] }
Proje kökünde { "name": "olcum-kitapligi", "type": "module", "version": "1.0.0" }
içeriğinde bir package.json bulunsun ve src/olcum.ts dosyası şu olsun:
export type Birim = "C" | "Pa" | "%"; export interface Olcum { readonly kimlik: string; deger: number; birim: Birim; } export function ortalama(kayitlar: readonly Olcum[]): number { if (kayitlar.length === 0) { return 0; } return kayitlar.reduce((t, k) => t + k.deger, 0) / kayitlar.length; } export const varsayilanBirim = "C";
Proje dizininde tsc çalıştırıldığında iki dosya üretilir. dist/olcum.js:
export function ortalama(kayitlar) { if (kayitlar.length === 0) { return 0; } return kayitlar.reduce((t, k) => t + k.deger, 0) / kayitlar.length; } export const varsayilanBirim = "C";
Ve dist/olcum.d.ts:
export type Birim = "C" | "Pa" | "%"; export interface Olcum { readonly kimlik: string; deger: number; birim: Birim; } export declare function ortalama(kayitlar: readonly Olcum[]): number; export declare const varsayilanBirim = "C";
İkisi birbirini tamamlar. JavaScript dosyasında tipler yoktur, gerçekleştirim vardır;
bildirim dosyasında gerçekleştirim yoktur, tipler vardır. declare sözcüğü tam olarak bunu
söyler: “böyle bir ad var, tipi budur, tanımı burada değil.”
Bu ayrım, ilk dersteki tip silme ilkesinin paket düzeyindeki karşılığıdır. Tip katmanı yayınlanan koddan ayrılmıştır; onu okumayan bir tüketici için paket sıradan bir JavaScript paketidir.
Bu dersteki rootDir ayarı, bu derleyici sürümünde outDir ile birlikte açıkça
yazılmalıdır; yazılmadığında TS5011 tanısı gelir. Ayarın işlevi çıktı dizin düzenini
belirlemektir: src/olcum.ts dosyası dist/olcum.js olur, dist/src/olcum.js değil.
Ortam Modülü Bildirimi
Tip bilgisi taşımayan bir kütüphane kullanıldığında, tipleri projede yazılabilir. Buna ortam bildirimi (ambient declaration) denir — gerçekleştirimi başka yerde olan bir şeyin tipini bildirmek.
Yapılandırmaya tipler dizini eklensin:
{ "compilerOptions": { "target": "es2022", "module": "nodenext", "moduleResolution": "nodenext", "strict": true, "noEmit": true }, "include": ["src", "tipler"] }
tipler/olcum-surucusu.d.ts dosyası, kütüphanenin sunduğu adları bildirir:
declare module "olcum-surucusu" { export interface SurucuAyarlari { adres: string; zamanAsimi?: number; } export function baglan(ayarlar: SurucuAyarlari): Promise<void>; export function oku(kanal: string): Promise<number>; }
Bu bildirimden sonra src/uygulama.ts içinde modül tiplenmiş olarak kullanılabilir:
import { baglan, oku } from "olcum-surucusu"; export async function ilkOkuma(): Promise<number> { await baglan({ adres: "10.0.0.7:9000" }); return oku("sicaklik.C"); } export async function hataliCagri(): Promise<number> { await baglan({ adres: "10.0.0.7:9000", yenidenDene: 3 }); return oku(42); }
src/uygulama.ts(9,42): error TS2353: Object literal may only specify known properties, and 'yenidenDene' does not exist in type 'SurucuAyarlari'. src/uygulama.ts(10,14): error TS2345: Argument of type 'number' is not assignable to parameter of type 'string'.
Elle yazılmış bildirim, derleyici için gerçek bir sözleşmedir ve tüm denetimler uygulanır.
Bir uyarı gerekir: bu bildirimin doğruluğu sınanmaz. Kütüphane gerçekte farklı davranıyorsa
derleyici bunu bilemez. Ortam bildirimi, as yazımı ve tip yüklemi gibi bir borçtur;
kütüphane sürümü değiştiğinde birlikte güncellenmesi gerekir. Bu nedenle, kütüphanenin
kendi bildirimlerini yayımladığı durumlarda elle yazılmış bildirim tercih edilmez.
Genel Kapsam Bildirimi
Bazı adlar bir modülden gelmez; çalışma zamanı tarafından genel kapsama konur. declare global bloğu bunları bildirir:
declare global { interface OlcumOrtami { readonly dugumAdi: string; readonly ornekleme: number; } const olcumOrtami: OlcumOrtami; } export {};
Sondaki export {}; satırı gereklidir: dosyanın bir modül sayılmasını sağlar ve declare global bloğu yalnızca modül dosyalarında yazılabilir.
Bildirimden sonra ad, import yazılmadan kullanılabilir:
export function ortamOzeti(): string { return `${olcumOrtami.dugumAdi} @ ${olcumOrtami.ornekleme}Hz`; } export function hataliErisim(): string { return olcumOrtami.bilinmeyenAlan; }
src/ortam.ts(6,22): error TS2339: Property 'bilinmeyenAlan' does not exist on type 'OlcumOrtami'.
Genel kapsam bildirimi güçlü ama dikkatli kullanılması gereken bir araçtır: bildirilen ad projenin her dosyasında görünür olur ve nereden geldiği kod okunarak anlaşılamaz. Bir adın gerçekten genel olması gerekmiyorsa, modülden dışa aktarmak yeğlenir.
Dış Tipleri Genişletme
Arayüzler dersinde tanıtılan bildirim birleştirme, asıl işlevini burada bulur. Bir
kütüphanenin tipi, kütüphaneye dokunmadan genişletilebilir. tipler/genisletme.d.ts
dosyası aynı modül adıyla ikinci bir blok açar:
declare module "olcum-surucusu" { interface SurucuAyarlari { yenidenDeneme?: number; } }
Aynı modül adını taşıyan ortam bildirimleri birleşir; SurucuAyarlari arayüzü de arayüz
olduğu için birleştirmeye açıktır. Sonuçta alan, asıl bildirim hiç değişmeden kullanılabilir
hâle gelir:
import { baglan, oku } from "olcum-surucusu"; export async function ilkOkuma(): Promise<number> { await baglan({ adres: "10.0.0.7:9000", yenidenDeneme: 3 }); return oku("sicaklik.C"); } export function ortamOzeti(): string { return `${olcumOrtami.dugumAdi} @ ${olcumOrtami.ornekleme}Hz`; }
Bu dosya, önceki üç bildirim dosyasıyla birlikte hatasız denetlenir.
Birleştirmenin gerçekten uygulandığı, alan adı yanlış yazıldığında görülür. Aynı dosyada
yenidenDeneme yerine yenidenDene yazıldığında:
src/uygulama.ts(4,42): error TS2561: Object literal may only specify known properties, but 'yenidenDene' does not exist in type 'SurucuAyarlari'. Did you mean to write 'yenidenDeneme'?
Genişletme dosyası projeden çıkarıldığında ise aynı satır için gelen tanı değişir:
src/uygulama.ts(4,42): error TS2353: Object literal may only specify known properties, and 'yenidenDene' does not exist in type 'SurucuAyarlari'.
İki tanı arasındaki fark — birinde öneri var, diğerinde yok — birleştirmenin uygulanıp uygulanmadığını doğrudan gösterir.
Genişletmenin sınırı, yalnızca arayüzlerde çalışmasıdır. Kütüphane tipini type ile
tanımlamışsa genişletilemez; Tip Takma Adları dersindeki TS2300 tanısı gelir. Kitaplık
yazarları için pratik sonuç şudur: dışa açılan nesne biçimleri arayüzle bildirilirse
tüketiciler genişletebilir.
Özet
- Bildirim dosyası yalnızca tip taşır;
declaresözcüğü bir adın var olduğunu ama tanımının başka yerde bulunduğunu söyler. declarationseçeneği bildirim dosyalarını kaynaktan üretir; bu derleyici sürümündeoutDirile birlikterootDirde yazılmalıdır.- Ortam modülü bildirimi, tip bilgisi taşımayan bir kütüphaneyi tipler; doğruluğu sınanmaz ve kütüphaneyle birlikte güncellenmesi gereken bir borçtur.
declare globalbloğu genel kapsamdaki adları bildirir; dosyanın modül olması içinexport {};satırı gerekir.importsatırı taşıyan birdeclare modulebloğu var olan modülün tiplerini genişletir; genişletme yalnızca arayüzlerde çalışır.
Sonraki Adım
Ortam bildirimi, tipsiz bir kütüphaneyi dışarıdan tiplemenin yoluydu. Peki projenin kendi JavaScript dosyaları? Var olan bir kod tabanı bir gecede TypeScript’e çevrilemez; bu geçişin kademeli yapılması gerekir. Sonraki ders JavaScript dosyalarının denetlenmesini, açıklamalarla tipleme yöntemini ve geçiş stratejisini ele alacak.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.