typescript - strictNullChecks etkinleştirilmişken undefined ile sayıları karşılaştırma


strictNullChecks harika bir seçenek, bu sayede geliştiricilerin birçok potansiyel çalışma zamanı hatasından kaçınmasına yardımcı olabilir. Bu yüzden kısa süre önce kodumu bu seçenek etkinleştirilmiş olarak yeniden yapılandırmaya başladım. Ama sonra küçük ama biraz rahatsız edici bir durumla karşılaştım:

if (array?.length > 0) {
    // do something with `array`
}

Boş olmayan bir dizi elde etmek için böyle bir sözdizimi kullanma alışkanlığım var; bu, herhangi bir şeyi undefined ile < veya > kullanarak karşılaştırmanın false ile sonuçlanması özelliğinden faydalanıyor. Ancak, bu sözdizimi strictNullChecks altında yasaklanmıştır, bu da onu ayrıntılı bir şekilde yazmam gerektiği anlamına geliyor:

if (array != null && array.length > 0) {
    // do something with `array`
}

Peki, belki o kadar ayrıntılı değil, ama array basit bir değişken yerine uzun bir zincirleme ifade olduğunda, önceki sözdizimi gerçekten hayatınızı kurtarır (aksi takdirde bu uzun ifadeyi tekrar etmek ile önceden bir değişkene atamak arasında bir seçim yapmanız gerekecektir).

Bu belirli senaryoya izin vermek için başka bir seçenek var mı? Çünkü strictNullChecks avantajını da kaybetmek istemiyorum.

Veya TypeScript'in undefined değerini diğer değerlerle < veya > kullanarak karşılaştırmayı yasaklamasının nedenleriyle ilgili bazı ilham verici fikirler de memnuniyetle karşılanır. Birçok kişinin bu özelliği, özellikle yeni başlayanlar için çok anlamlı olmadığından, her ne suretle olursa olsun kaçınılması gereken bir tuzak olarak gördüğünü anlıyorum. Ama böyle bir senaryoda kullanmanın kolaylığını takdir ediyorum. Peki onu yasaklamada tek göz önünde bulundurulan husus açıklık mı? Yoksa gözden kaçırdığım bazı potansiyel çalışma zamanı etkileri de var mı?


Yorumlarda da belirtildiği gibi, yukarıdaki senaryo basitçe > 0 ifadesini kaldırarak çözülebilir, çünkü hem undefined hem de 0 kullanıcıya göre yanlış (falsy) olarak kabul edilir.
Muhtemelen undefined veya null olabilecek bir değeri sıfır olmayan bir sayı ile karşılaştırmak istediğimiz başka senaryolar olsa da, array?.length ?? 0 işimizi görecektir (ancak TypeScript, sonraki blokta array'in ne undefined ne de null olduğunu çıkaramayacaktır, bu yüzden hala null olmayan doğrulama operatörünü kullanmamız gerekecek).
Yani temel sorun büyük ölçüde çözülmüş durumda. Ama hâlâ merak ediyorum, TypeScript geliştiricilerini strictNullChecks açıkken muhtemelen null veya undefined sayılarla karşılaştırmayı yasaklamaya iten motivasyon nedir. Bu nedenle, bu soruyu tartışmaya açık bırakmaya karar verdim.

Cevap #1

Fark ettiğiniz gibi array?.length > 0 strictNullChecks ile izin verilmez: Eğer array tanımsızsa, bu undefined > 0 şeklinde basitleşir.

If koşulu, strictNullChecks ile iyi çalışan bir şekilde basitleştirilebilir.

if (array?.length) {
   // process non-empty array
}

Yukarıdaki kod, undefined ve 0'ın yanlış (falsy) olduğunu ve sıfır olmayan tüm sayıların doğru (truthy) olduğunu gerçeğine dayanır.

Eğer if bloğu içindeki kod boş dizileri kabul edebiliyorsa, koşul şu şekilde daha da basitleştirilebilir:

if (array) {
   // process empty array or non-empty array
}

Tasarım kararlarını tartışma pozisyonunda olmasam da, strictNullChecks şöyle diyor:

strictNullChecks açık olduğunda, bir değer null veya undefined ise, o değer üzerinde yöntemleri veya özellikleri kullanmadan önce bu değerleri test etmeniz gerekecektir.

Eğer muhtemelen tanımsız olan bir nesne üzerinde özellik veya yöntem erişimi yasaklanmışsa, < ve <= operatörlerinin de yasaklanması tutarlıdır. Sadece tutarlı olmakla kalmaz, aynı zamanda JS'in şaşırtıcı davranışını ortadan kaldırır: Neden undefined 1'den küçük değil?

// JS
undefined <= undefined  // false
undefined > undefined   // false  

Cevap #2

Daha önce @Lesiak'in belirttiği gibi, undefined, strictNullChecks etkinleştirildiğinde numberlerle karşılaştırılamaz.

Boş olmayan dizilerin kontrol edilmesi durumları dışında (bu, @Lesiak'ın cevabında ele alınmıştır), belirli değerin bir number ile karşılaştırılmadan önce undefined olmadığını kontrol edebilirsiniz:

interface Example {
  value: number | undefined;
}

const e: Example = { ... };

if (e.value !== undefined && e.value > 12345) {
  // ...
}

https://www.typescriptlang.org/play/?#code/JYOwLgpgTgZghgYwgAgKIA84FsAOAbFAbwFgAoZZANzjwFcIAuZEWrAI2mQB9laQATCDFAR+AbjIBfMmQQB7EAGcwyRmky4CyALzJCVGvSZ9BwkKOSSJpMgHpbyAAJhFAWgjocEBGHdQoclBkwDDIABQQAHTUdCgAfMgAjABMAMwALACsAJR6ZBT2yJHFUjKkhQDqgQDWigCEwaER0YYoddq6JkIi-MgAZH2qLbHICSkZOXnkyIXFkVJAA

İlgili makaleler