javascript - Neden TypeScript, gerekli parametrelerden sonra isteğe bağlı parametreler gerektirir?


Bu işe yarıyor:

public console(message: string | undefined, suppressLevel: boolean) {}

Ama bu yapmaz:

public console(message?: string, suppressLevel: boolean) {}

?'nin temelde | undefined için bir kısayol gibi göründüğü (ve VS Code'da üzerine geldiğinizde sadece bunu söylediği) göz önüne alındığında, TypeScript neden bir ayrım yapıyor? Bir isteğe bağlı parametre için açıkça undefined iletebilirsiniz ve bu, sonunu belirtmemekle aynı olurdu.

Cevap #1

En önemlisi, bu, bir fonksiyon imzasını güçlü bir şekilde türlendirmekle sadece daha belirgin hale getirilen bir javascript gerçeğidir.

Fonksiyon parametreleri, argümanlar listesinde pozisyonel olarak bağlanır. İlk geçirilen argüman ilk parametreye bağlanır. İkinci geçirilen argüman ikinci parametreye bağlanır. Ve bu şekilde devam eder. Sondaki isteğe bağlı parametrelerle, bir JavaScript motoru, argüman listesi çok kısa olduğunda son parametreleri undefined olarak bağlayacağını bilir. Çağrı ne kadar kısa olursa olsun, o kadar çok son parametre undefined olur.

Eğer isteğe bağlı parametreler ortada veya başta olabilseydi, çağrı yapılan yerde hangi parametrelerin hangi argümanlara bağlanması gerektiğini bilmek için yeterli bilgi olmazdı.

function fn(a?: number, b: number) { /* ... */ }

fn(42);

Eğer fn'in imzası geçerli olsaydı, fn(42) belirsiz olurdu. b 42 olarak mı bağlansın ve a undefined mi kalsın? Yoksa a 42 olarak mı bağlansın ve b undefined mi kalsın (ve dolayısıyla bir tip hatası mı oluşsun)? Bu özel durumda, typescript tip denetleyicisinin HATA olmadığını KABUL etmesini ve bunun yerine çağrının geçerli bir yorumunu bulmak için elinden geleni yapmasını isteyebilirsiniz (yani b 42 alır), ancak bu daha maliyetli bir aşırı yük çözümleme algoritması olurdu ve yine de belirsiz durumlar olurdu ve kurallar çok karmaşık hale gelirdi ve kullanışlı olmazdı (örneğin fn2(a?: number, b: number, c?: number) { /* ... */ } ile fn(42, 3.1415)).

Javascript, sıralı argümanlara sahip olarak ve son argümanları isteğe bağlı hale getirerek, ve Typescript'in izin verilen imza aşırı yüklemelerini açıkça not etmemize izin vermesiyle, ifade gücü, makuliyet (tip denetleyicisinin performansı) ve hata önleme açısından harika bir denge sağlar.

Eğer aşırı yük çözümü bu şekilde daha esnek olsaydı, o zaman geçerli olarak kabul edilecek daha fazla çağrıyı değerlendirmek zorunda kalırdı ki bunlar aslında hatalar olabilir. Veya tüm parametre kombinasyonlarını birbirleriyle birleştirilmiş türler haline getirip ardından bunları kodda ayırmak gibi tüm varyasyonlarla başa çıkmak fonksiyon gövdesinin üzerine yük bindirirdi, bu da okunmasını zorlaştırırdı.

Cevap #2

?, string | undefined için kısayol değildir. Bu, isteğe bağlı bir parametredir. Yani - beklenen değer türünü geçirebilirsiniz veya geçirmeyebilirsiniz.

string | undefined, buna karşılık, ya bir string ya da undefined olan bir değeri açıkça geçirmeniz gerektiği anlamına gelir. Değer undefined olabilir, ama parametre yine de vardır.

Opsiyonel bir özelliğin ardından bir özellik geçirmek paradoksal olurdu - çünkü onu ayarlayamazsınız, çünkü onu ayarlamak, ondan önceki bir özelliği ayarlamak anlamına gelir, bu da onun öncülünün artık opsiyonel olmadığı anlamına gelir!

İlgili makaleler