- Konu sahibi
- #1
İlk olarak hatanın nedenini ayırın: TypeScript, bir değişkenin
Örneğin aşağıdaki kodda
Buradaki sorun,
Değerin bulunmadığı durumda başka bir işlem yapılacaksa en güvenli yöntem açık bir kontrol yazmaktır:
Bu örnekte
Buradaki
Değer bulunamadığında kullanılacak makul bir alternatif varsa
Buna karşılık
Burada
Aynı işi parametre için de yapabilirsiniz:
İlk çağrıda parametre verilmediği için sonuç
Bir nesnenin kendisi veya içindeki alanlar bulunmayabiliyorsa, her seviyeyi ayrı ayrı kontrol etmek yerine isteğe bağlı zincirleme operatörünü kullanabilirsiniz:
Bir fonksiyon her durumda değer döndürmüyorsa TypeScript bunu
Bu tür bir fonksiyonda tüm yolların aynı sonucu üretmesini sağlayın veya dönüş türünü açıkça genişletin. Değer bulunamaması beklenen bir durumsa
Burada
Burada
Bir alanın gerçekten boş olabilmesi normal ise türüne bunu ekleyin:
Buradaki
API yanıtlarında da aynı ayrımı yapın. Sunucu alanı hiç göndermiyorsa
Aşağıdaki kullanım TypeScript hatasını susturur:
Bu örnekte kontrol başarısız olursa hata açık bir nedenle durur; başarılı olursa sonraki satırda
Sorunun kaynağına göre uygulanacak yaklaşım değişir:
Tabloya göre karar verirken yalnız derleyici hatasını kaldırmayı değil, eksik değerin uygulamadaki anlamını dikkate alın. Kullanıcıya “bulunamadı” gösterilmesi gereken bir durumda varsayılan değer vermek sorunu gizleyebilir. Buna karşılık isteğe bağlı profil açıklaması gibi bir alanda varsayılan metin kullanmak doğru olabilir.
Bu hataların görünmesi çoğu zaman
Bu nedenle izlenecek sıra şöyledir:
null veya undefined olabileceğini biliyorsa, o değişkeni kontrol etmeden kullanmanıza izin vermez. Çözüm; değerin gerçekten zorunlu olup olmadığını belirlemek, zorunlu değilse kontrol veya varsayılan değer kullanmak, zorunluysa türü ve verinin üretildiği yeri düzeltmektir. Sadece hata mesajını susturmak için ! kullanmak ise değerin gerçekten mevcut olduğunu kanıtlamaz ve çalışma zamanında yeni bir hata oluşturabilir.Hatanın temel nedeni: değer henüz mevcut olmayabilir
null, bilerek boş bırakılmış bir değeri; undefined ise çoğunlukla henüz değer atanmamış, bulunamamış veya bir fonksiyonun değer döndürmemiş olmasını ifade eder. TypeScript’in strictNullChecks seçeneği etkin olduğunda, string türü yalnızca metin kabul eder; null ve undefined bu türe kendiliğinden dahil değildir.Örneğin aşağıdaki kodda
isim değişkeni bir metin veya undefined olabilir:
Kod:
function kullaniciAdiGetir(): string | undefined {
return undefined;
}
const isim = kullaniciAdiGetir();
console.log(isim.toUpperCase());
Buradaki sorun,
toUpperCase() çağrısının yalnızca gerçekten bir metin varsa güvenli olmasıdır. Fonksiyon undefined döndürürse JavaScript çalışma zamanında hata oluşur. TypeScript’in derleme aşamasında bu kullanımı engellemesi, hatayı çalıştırmadan önce fark etmenizi sağlar.Değeri kullanmadan önce kontrol edin
Değerin bulunmadığı durumda başka bir işlem yapılacaksa en güvenli yöntem açık bir kontrol yazmaktır:
Kod:
function kullaniciAdiGetir(): string | undefined {
return undefined;
}
const isim = kullaniciAdiGetir();
if (isim !== undefined) {
console.log(isim.toUpperCase());
} else {
console.log("Kullanıcı adı bulunamadı.");
}
Bu örnekte
if bloğunun içinde TypeScript, isim değişkeninin artık string olduğunu anlar. else bloğu ise değerin bulunamadığı durumu ayrıca ele alır. Bu kontrol, değerin mevcut olduğunu garanti eder; ancak verinin neden bulunamadığını açıklamaz. Değerin bir API yanıtından, formdan veya veritabanından gelmesi durumunda bu neden ayrıca incelenmelidir.null ve undefined değerlerinin ikisini birden kontrol etmek istediğinizde eşitsizlik kontrolü kullanabilirsiniz:
Kod:
const aciklama: string | null | undefined = getAciklama();
if (aciklama != null) {
console.log(aciklama.trim());
}
Buradaki
!= null ifadesi hem null hem de undefined değerlerini dışarıda bırakır. Bu kullanım, iki değeri tek tek karşılaştırmaktan daha kısadır. Ancak 0, false veya boş metin gibi geçerli değerleri de reddetmek istemiyorsanız if (aciklama) biçimindeki doğruluk kontrolünü gelişigüzel kullanmayın.Değer yoksa varsayılan değer verin
Değer bulunamadığında kullanılacak makul bir alternatif varsa
?? operatörünü kullanın:
Kod:
const kullaniciAdi: string | undefined = getKullaniciAdi();
const gorunenAd = kullaniciAdi ?? "Misafir";
console.log(gorunenAd.toUpperCase());
?? yalnızca sol taraftaki değer null veya undefined olduğunda sağdaki değeri kullanır. Bu nedenle 0, false ve "" gibi değerler korunur.Buna karşılık
|| operatörü tüm falsy değerlerde sağdaki seçeneğe geçer:
Kod:
const sayfaBoyutu = 0;
const sonuc = sayfaBoyutu || 10; // 10
const digerSonuc = sayfaBoyutu ?? 10; // 0
Burada
0 geçerli bir değer olabiliyorsa || yanlış sonuç üretir. Varsayılan değer yalnızca boşluk durumunda kullanılacaksa ?? daha doğru seçimdir.Aynı işi parametre için de yapabilirsiniz:
Kod:
function selamla(isim?: string): string {
const kullanilacakIsim = isim ?? "Misafir";
return `Merhaba ${kullanilacakIsim}`;
}
console.log(selamla());
console.log(selamla("Ayşe"));
İlk çağrıda parametre verilmediği için sonuç
Merhaba Misafir olur. İkinci çağrıda verilen isim korunur. Bu çözüm, değerin yokluğunun uygulama açısından normal olduğu durumlar içindir; zorunlu bir kullanıcı adı veya kimlik için sessizce varsayılan değer vermek yanlış olabilir.İç içe nesnelerde güvenli erişim kullanın
Bir nesnenin kendisi veya içindeki alanlar bulunmayabiliyorsa, her seviyeyi ayrı ayrı kontrol etmek yerine isteğe bağlı zincirleme operatörünü kullanabilirsiniz:
Kod:
type Kullanici = {
profil?: {
sehir?: string;
};
};
const kullanici: Kullanici = {};
const sehir = kullanici.profil?.sehir;
console.log(sehir ?? "Şehir bilgisi yok");
kullanici.profil?.sehir ifadesi, profil yoksa hata vermek yerine undefined üretir. Bu operatör hatayı çözmüş sayılmaz; yalnızca eksik veriyi güvenli biçimde undefined olarak taşır. Değer zorunluysa, devam eden kodda kontrol etmeniz veya açık bir hata üretmeniz gerekir.Fonksiyon dönüş türünü ve erken dönüşleri düzeltin
Bir fonksiyon her durumda değer döndürmüyorsa TypeScript bunu
undefined ihtimali olarak değerlendirir. Aşağıdaki örnekte yalnızca koşul sağlanırsa değer döndürülür:
Kod:
function dosyaUzantisi(dosyaAdi: string): string {
if (dosyaAdi.includes(".")) {
return dosyaAdi.split(".").pop() as string;
}
// Koşul sağlanmadığında dönüş yok
}
Bu tür bir fonksiyonda tüm yolların aynı sonucu üretmesini sağlayın veya dönüş türünü açıkça genişletin. Değer bulunamaması beklenen bir durumsa
string | undefined kullanıp çağıran yerde kontrol etmek daha doğrudur:
Kod:
function dosyaUzantisi(dosyaAdi: string): string | undefined {
const noktaKonumu = dosyaAdi.lastIndexOf(".");
if (noktaKonumu === -1 || noktaKonumu === dosyaAdi.length - 1) {
return undefined;
}
return dosyaAdi.slice(noktaKonumu + 1);
}
const uzanti = dosyaUzantisi("rapor.pdf");
if (uzanti === undefined) {
console.log("Dosyanın uzantısı yok.");
} else {
console.log(`Uzantı: ${uzanti}`);
}
Burada
undefined bir programlama kazası değil, fonksiyonun tanımlı sonucu olarak kullanılır. Çağıran kodun bu durumu ele alması gerekir. as string ile türü zorla string yapmak ise fonksiyonun gerçekten her zaman metin döndürmesini sağlamaz; yalnızca derleyiciye varsayımınızı bildirir.Dizi aramalarında undefined sonucunu unutmayın
find() gibi metotlar aranan öğeyi bulamazsa undefined döndürebilir:
Kod:
type Urun = {
id: number;
ad: string;
};
const urunler: Urun[] = [
{ id: 1, ad: "Klavye" }
];
const urun = urunler.find((oge) => oge.id === 2);
if (urun === undefined) {
console.log("Ürün bulunamadı.");
} else {
console.log(urun.ad);
}
Burada
urun değişkenini doğrudan urun.ad biçiminde kullanmak güvenli değildir. Arama sonucunun boş olması, dizinin bozuk olduğunu kanıtlamaz; yalnızca verilen ölçüte uyan öğe bulunmadığını gösterir. Uygulama açısından ürünün bulunamaması hata ise kullanıcıya açıklama gösterebilir veya çağıran koda hata döndürebilirsiniz.Tür tanımını verinin gerçeğine göre yazın
Bir alanın gerçekten boş olabilmesi normal ise türüne bunu ekleyin:
Kod:
type Ayarlar = {
tema: "acik" | "koyu";
dil?: string;
};
function ayarDiliniGoster(ayarlar: Ayarlar): string {
return ayarlar.dil ?? "tr";
}
Buradaki
dil? alanın gönderilmesinin zorunlu olmadığını belirtir. Alan her zaman gelmek zorundaysa soru işaretini kaldırıp eksik veriyi kaynağında düzeltin. Türü gereksiz biçimde string | null | undefined yapmak, her kullanım noktasına ek kontrol taşır ve veri sözleşmesindeki problemi gizleyebilir.API yanıtlarında da aynı ayrımı yapın. Sunucu alanı hiç göndermiyorsa
undefined, alanı açıkça boş gönderiyorsa null alabilirsiniz. Bu iki durum uygulamanız için farklı anlama geliyorsa türü buna göre tanımlayın ve yanıtı kullanan kodda iki durumu ayrı ele alın.Non-null assertion operatörünü yalnız kanıt varsa kullanın
Aşağıdaki kullanım TypeScript hatasını susturur:
Kod:
const eleman = document.querySelector("#baslik");
eleman!.textContent = "Hazır";
! işareti, “Bu değer burada kesinlikle boş değil” varsayımını derleyiciye bildirir. Fakat DOM içinde #baslik bulunmuyorsa çalışma zamanında hata almaya devam edersiniz. Bu nedenle önce kontrol etmek daha güvenlidir:
Kod:
const eleman = document.querySelector("#baslik");
if (eleman === null) {
throw new Error("#baslik elementi bulunamadı.");
}
eleman.textContent = "Hazır";
Bu örnekte kontrol başarısız olursa hata açık bir nedenle durur; başarılı olursa sonraki satırda
eleman güvenli biçimde kullanılabilir. ! ancak değerin varlığı başka bir doğrulanmış koşulla gerçekten garanti ediliyorsa tercih edilmelidir.Hangi çözümü seçmelisiniz?
Sorunun kaynağına göre uygulanacak yaklaşım değişir:
| Durum | Uygun yaklaşım |
|---|---|
| Değer normal olarak bulunmayabilir | Kontrol yazın veya ?? ile varsayılan değer verin. |
| Değer zorunlu olmalı, fakat eksik geliyor | Üretildiği yeri, API yanıtını veya fonksiyon akışını düzeltin. |
| İç içe alanlar eksik olabilir | ?. ile güvenli erişin, ardından gerekirse ?? kullanın. |
| Dizi araması sonuç vermeyebilir | find() sonucunu undefined açısından kontrol edin. |
| Değerin kesinlikle mevcut olduğu kanıtlanmış | Gerekirse ! kullanılabilir; bunun çalışma zamanı kontrolü olmadığını unutmayın. |
tsconfig ayarını kontrol edin
Bu hataların görünmesi çoğu zaman
strictNullChecks seçeneğinin etkin olmasından kaynaklanır. Bu seçenek, null ve undefined değerlerinin diğer türlerle karıştırılmasını sınırlar. Hatayı kapatmak için bu denetimi devre dışı bırakmak, mevcut kodu derletse bile çalışma zamanı hatalarını ortadan kaldırmaz.Bu nedenle izlenecek sıra şöyledir:
- Hata verilen değişkenin türünde
nullveyaundefinedbulunup bulunmadığını okuyun. - Değerin neden boş olabildiğini belirleyin: isteğe bağlı alan mı, başarısız arama mı, eksik dönüş mü, yoksa hatalı veri akışı mı?
- Değer normal olarak boş olabiliyorsa kontrol,
??veya?.kullanın. - Değer zorunluysa onu üreten fonksiyon, API yanıtı veya koşul akışını düzeltin.
- Kodu derleyin ve yalnız derleme hatasının kaybolduğunu değil, boş değer durumunda beklenen davranışın oluştuğunu kontrol edin.
as string veya ! kullanımı yalnız TypeScript’in uyarısını kaldırabilir. Gerçek çözüm, boş değerin uygulama tarafından nasıl ele alınacağını açıkça belirlemektir.Sık sorulan sorular
null ile undefined arasındaki fark neden önemlidir?
null çoğunlukla bilerek boş bırakılmış değeri, undefined ise değer atanmamasını veya bir sonucun bulunamamasını ifade eder. Uygulamanız bu iki durumu aynı kabul ediyorsa != null veya ?? yeterli olabilir. Farklı anlam taşıyorlarsa ikisini ayrı kontrollerle ele almalısınız.Hata vermemesi için her yerde || kullanabilir miyim?
Hayır.
||, 0, false ve boş metin gibi geçerli değerleri de yok kabul eder. Yalnızca null veya undefined için varsayılan değer gerekiyorsa ?? kullanın.any kullanmak bu hatayı çözer mi?
any, TypeScript’in tür denetimini büyük ölçüde devre dışı bırakır; değerin gerçekten mevcut olduğunu garanti etmez. Bu nedenle hata derleme aşamasında görünmeyebilir, fakat uygulama çalışırken devam edebilir. Sorunun kaynağını kontrol etmek genellikle daha güvenlidir.